package main

import (
	"./etdd"
	"flag"
	"fmt"
	"os"
	"path/filepath"
	"sync"
)

type result struct {
	handler *etdd.Logger
	file    string
}

func main() {

	input := flag.String("i", "**.dm_84", "demo filename mask")
	output := flag.String("o", "etdd.log", "output file name (use -- for standard output)")
	colors := flag.Bool("c", false, "don't strip color codes")

	flag.Parse()

	files, err := filepath.Glob(*input)

	if err != nil {
		panic(err)
	}

	fmt.Printf("> ETDD v1.1 - Enemy Territory demo decoder\n")
	fmt.Printf("> a domestic cat (c) 2019\n\n")

	if len(files) == 0 {
		_, _ = fmt.Fprintf(os.Stderr, "No input files. Use --help.\n")
	}

	writeTo := os.Stdout
	writeErr := os.Stderr

	if *output != "--" {

		writeTo, err = os.Create(*output)

		if err != nil {
			panic(err)
		}

		writeErr = writeTo

	}

	// RC vulnerable.
	etdd.HuffInit()

	mutex := &sync.Mutex{}
	var wait sync.WaitGroup
	limiter := make(chan int, 16)

	n := 0
	var results []*result

	for _, file := range files {

		limiter <- 1
		wait.Add(1)

		mutex.Lock()
		handler := etdd.NewLogger(*colors)
		results = append(results, &result{&handler, file})
		mutex.Unlock()

		go func(file string, handler *etdd.Logger) {

			defer wait.Done()

			handler.Write("Demo: " + file + "\n")

			demo, err := etdd.Open(file)

			if err == nil {
				demo.Read(handler)
				demo.Close()
			} else {
				handler.Error(err)
				handler.End()
			}

			<-limiter

			mutex.Lock()
			completed := 0

			for _, done := range results {

				if !done.handler.Complete {
					break
				}

				completed++
				n++

				done.handler.WriteTo(writeTo, writeErr)

				if *output != "--" {
					fmt.Printf("[%05d/%05d]: %s\n", n, len(files), done.file)
				}

			}

			if completed > 0 {
				results = results[completed:]
			}

			mutex.Unlock()

		}(file, &handler)

	}

	wait.Wait()

}