package cmd

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"os"
	"path/filepath"

	"code.justin.tv/cplat/twitchling/cmd/twitchling/clients"
	"code.justin.tv/cplat/twitchling/cmd/twitchling/format"
	"code.justin.tv/cplat/twitchling/localization/language"
	"code.justin.tv/cplat/twitchling/project"
	"github.com/spf13/cobra"
)

var downloadDir string

var downloadCmd = &cobra.Command{
	Use:   "download",
	Short: "download translations from Smartling and generate a bundle",
	Long:  ``,
	RunE:  runDownload,
}

func init() {
	rootCmd.AddCommand(downloadCmd)

	downloadCmd.Flags().StringVarP(&downloadDir, "out-dir", "o", "./translations", "location to download translations to (default is ./translations)")
}

func runDownload(cmd *cobra.Command, args []string) error {
	project, err := project.LoadProject(projectFile)
	if err != nil {
		return err
	}

	fmt.Printf("Downloading translations from Smartling for project %s...\n", projectFile)

	secret, err := clients.GetSandstormSecret(&project.Config)
	if err != nil {
		return err
	}

	err = downloadTranslations(cmd, project, secret)
	if err != nil {
		return err
	}

	fmt.Println("DONE: Download completed.")

	return nil
}

// TODO: Improve the sort of error messages this produces.
func downloadTranslations(cmd *cobra.Command, project *project.Project, secret string) error {
	smartling := clients.NewSmartlingClient(project.Config.Smartling.UserID, secret)
	// NOTE: Smartling doesn't support some languages, so instead substitute them.
	substitutes := map[language.Tag]language.Tag{
		language.MustParse("en-GB"): language.DefaultLanguage,
	}

	err := os.MkdirAll(downloadDir, 0755)
	if err != nil {
		return fmt.Errorf("failed to create directory: %s", downloadDir)
	}

	for _, lang := range language.SupportedLanguages {
		downloadLang := lang
		substitute, exists := substitutes[downloadLang]
		if exists {
			downloadLang = substitute
		}

		cmd.Printf("Downloading translation %s...\n", lang)
		translation, err := smartling.DownloadTranslation(project, downloadLang)
		if err != nil {
			return err
		}

		var pass, fail int
		result := translation.Validate()
		for _, m := range result.Results {
			if m.Error != nil {
				fail++
				cmd.PrintErrf("--- %s: id: %s, variant: %s\n", format.RedBold("FAIL"), m.ID, m.Variant)
				cmd.PrintErrln(format.FormatError(m.ID, m.Variant, m.Error))
			} else {
				pass++
				cmd.Printf("--- %s: id: %s, variant: %s\n", format.GreenBold("PASS"), m.ID, m.Variant)
			}
		}

		cmd.Printf("DONE Pass: %d, Fail: %d.\n", pass, fail)
		if fail > 0 {
			return fmt.Errorf("found invalid messages in input")
		}

		cmd.Printf("Downloaded translation %s\n", lang)

		data, err := json.Marshal(translation)
		if err != nil {
			return err
		}

		filename := filepath.Join(downloadDir, fmt.Sprintf("%s.json", lang))
		err = ioutil.WriteFile(filename, data, 0644)
		if err != nil {
			return err
		}
	}

	return nil
}
