package utils

import (
	"fmt"
	"github.com/urfave/cli/v2"
	"net"
	"strings"
	"sync"
)

func getData(domain string, logIp bool) string {
	ips, _ := net.LookupIP(domain)

	var filteredIps []string

	for _, ip := range ips {
		if !ip.IsLoopback() {
			filteredIps = append(filteredIps, ip.String())
		}
	}

	if len(filteredIps) > 0 {
		if logIp {
			return fmt.Sprintf(
				"%s\t%s", domain, strings.Join(filteredIps, " "),
			)
		}
	}

	return ""
}

func runWorker(
	domain string,
	tlds chan string,
	logIp bool,
) <-chan string {
	results := make(chan string)

	go func() {
		defer close(results)
		for tld := range tlds {
			if result := getData(domain+tld, logIp); result != "" {
				results <- result
			}
		}
	}()

	return results
}

func merge(cs ...<-chan string) <-chan string {
	var wg sync.WaitGroup
	out := make(chan string)

	output := func(c <-chan string) {
		defer wg.Done()
		for n := range c {
			out <- n
		}
	}

	wg.Add(len(cs))
	for _, c := range cs {
		go output(c)
	}

	go func() {
		wg.Wait()
		close(out)
	}()

	return out
}

func ProcessCli(cCtx *cli.Context) error {
	tlds := cCtx.String("tlds")
	threads := cCtx.Int("threads")

	var tldsList []string

	if tlds != "" {
		if err := ReadFileLines(tlds, &tldsList); err != nil {
			return err
		}
	}

	for argsIndex := 0; argsIndex < cCtx.Args().Len(); argsIndex++ {
		domain := cCtx.Args().Get(argsIndex)
		if tlds != "" {
			domain = domain + "."
		}

		tldsLine := make(chan string, 1)

		workers := make([]<-chan string, threads)
		for i := 0; i < threads; i++ {
			workers[i] = runWorker(domain, tldsLine, true)
		}

		for _, tld := range tldsList {
			tldsLine <- tld
		}

		close(tldsLine)

		for result := range merge(workers...) {
			fmt.Println(result)
		}
	}

	return nil
}