package got

import (
	"fmt"
	"io/ioutil"
	"os"
	"os/exec"
	"path/filepath"
	"strings"

	. "git.eugeniocarvalho.dev/eugeniucarvalho/apicodegen/common"
)

var (
	OutputDirectory  string
	CurrentDirectory string
)

func Translate(p *Project) (err error) {

	if err = initGlobalVars(p); err != nil {
		fmt.Println("error initGlobalVars")
		return
	}
	if err = CreateMainFile(p); err != nil {
		fmt.Println("error CreateMainFile")
		return
	}
	if err = createParamsFile(p); err != nil {
		fmt.Println("error createParamsFile")
		return
	}

	if err = CreateEnvironment(p); err != nil {
		fmt.Println("error CreateEnvironment")
		return
	}

	if err = CreateVariables(p); err != nil {
		fmt.Println("error CreateVariables")
		return
	}

	if err = GenSchemas(p); err != nil {
		fmt.Println("error GenSchemas")
		return
	}

	if err = GenResources(p); err != nil {
		fmt.Println("error GenResources")
		return
	}

	if err = GenMiddlewares(p); err != nil {
		fmt.Println("error GenMiddlewares")
		return
	}

	return include(p)
}

func createSymbolicLinks(basedir string) func(string, os.FileInfo, error) error {
	var (
		callback func(string, os.FileInfo, error) error
		input    []byte
		relative = func(path string) string {
			return fmt.Sprintf("%s/%s%s", OutputDirectory, "v1", strings.Replace(filepath.Dir(path), basedir, "", 1))
		}
	)

	callback = func(pathX string, infoX os.FileInfo, errX error) (err error) {

		if errX != nil {
			fmt.Printf("error 「%v」 at a path 「%q」\n", errX, pathX)
			return errX
		}

		if infoX.IsDir() {
			relativedir := strings.Replace(pathX, basedir, "", 1)
			if relativedir != "" {

				// fmt.Println("crinado diretorio", fmt.Sprintf("%s/%s%s", OutputDirectory, "v1", relativedir))

				os.MkdirAll(fmt.Sprintf("%s/%s%s", OutputDirectory, "v1", relativedir), 0777)
			}

		} else {
			// fmt.Println("crinado link symbolico aqui", relative(pathX))
			// os.Symlink(pathX, filepath.Join(relative(pathX), infoX.Name()))

			if input, err = ioutil.ReadFile(pathX); err != nil {
				return
			}

			// fmt.Println("READ FILE", pathX, filepath.Join(relative(pathX), infoX.Name()))

			if err = ioutil.WriteFile(
				filepath.Join(relative(pathX), infoX.Name()),
				input,
				0644,
			); err != nil {
				return
			}

			// fmt.Printf("  dir ------ : 「%v」\n", pathX)
			// fmt.Printf("  dir: 「%v」\n", strings.Replace(filepath.Dir(pathX), basedir, "", 1))
			// fmt.Printf("  file name 「%v」\n", infoX.Name())
			// fmt.Printf("  extenion: 「%v」\n", filepath.Ext(pathX))
			// fmt.Printf("  target: 「%v」\n", relative(pathX))
			// fmt.Sprintf("%s/%s%s", OutputDirectory, "v1", strings.Replace(filepath.Dir(pathX), basedir, "", 1)),
		}

		return nil
	}
	return callback
}

func include(p *Project) error {
	var err error

	if err = exec.Command("sh", "-c", fmt.Sprintf("find %s -type l -delete", OutputDirectory)).Run(); err != nil {
		fmt.Println("include error ", err)
	}

	basedir := fmt.Sprintf("%s/include/go", CurrentDirectory)

	if err = filepath.Walk(basedir, createSymbolicLinks(basedir)); err != nil {
		return err
	}
	return err
}

func initGlobalVars(p *Project) error {
	var err error

	if CurrentDirectory, err = os.Getwd(); err != nil {
		return err
	}

	if OutputDirectory, err = filepath.Abs(CurrentDirectory + "/" + p.OutPath); err != nil {
		return err
	}
	return nil
}
