package clients

import (
	"encoding/json"
	"io/ioutil"

	"code.justin.tv/cplat/twitchling/localization/language"
	"code.justin.tv/cplat/twitchling/project"
	smartling "github.com/Smartling/api-sdk-go"
)

type SmartlingClient interface {
	UploadProject(project *project.Project) error
	DownloadTranslation(project *project.Project, tag language.Tag) (*project.MessageSet, error)
}

type smartlingClient struct {
	client *smartling.Client
}

func NewSmartlingClient(userID string, tokenSecret string) SmartlingClient {
	client := smartling.NewClient(userID, tokenSecret)

	return &smartlingClient{
		client,
	}
}

func (c *smartlingClient) UploadProject(project *project.Project) error {
	data, err := serializeProjectForUpload(project)
	if err != nil {
		return err
	}

	request := smartling.FileUploadRequest{
		FileURIRequest: smartling.FileURIRequest{
			FileURI: project.Config.Smartling.FileURI,
		},
		File:     data,
		FileType: smartling.FileTypeJSON,
	}

	_, err = c.client.UploadFile(project.Config.Smartling.ProjectID, request)

	return err
}

func (c *smartlingClient) DownloadTranslation(proj *project.Project, tag language.Tag) (*project.MessageSet, error) {
	request := smartling.FileDownloadRequest{
		FileURIRequest: smartling.FileURIRequest{
			FileURI: proj.Config.Smartling.FileURI,
		},
		Type:            "published",
		IncludeOriginal: false,
	}

	reader, err := c.client.DownloadTranslation(proj.Config.Smartling.ProjectID, tag.String(), request)
	if err != nil {
		return nil, err
	}

	data, err := ioutil.ReadAll(reader)
	if err != nil {
		return nil, err
	}

	var result project.MessageSet
	err = json.Unmarshal(data, &result)
	if err != nil {
		return nil, err
	}

	return &result, nil
}

type smartlingTranslatePath struct {
	Path        string   `json:"path"`
	Key         []string `json:"key"`
	Instruction string   `json:"instruction"`
}

type smartlingSettings struct {
	TranslatePaths          []smartlingTranslatePath `json:"translate_paths"`
	PluralsDetection        string                   `json:"plurals_detection"`
	StringFormat            string                   `json:"string_format"`
	PlaceholderFormatCustom []string                 `json:"placeholder_format_custom"`
}

type smartlingProject struct {
	// NOTE: smartlingSettings **MUST** be the first member or Smartling will break in incredible ways!
	Smartling smartlingSettings `json:"smartling"`
	project.MessageSet
}

func serializeProjectForUpload(project *project.Project) ([]byte, error) {
	// NOTE: These smartling project settings are hard coded to abstract these details away from consumers of the CLI
	smartlingProject := smartlingProject{
		Smartling: smartlingSettings{
			TranslatePaths: []smartlingTranslatePath{
				{
					Path:        "/messages/variants/*",
					Key:         []string{"/messages/id", "{*}"},
					Instruction: "/messages/translationNote",
				},
			},
			PluralsDetection:        "on",
			StringFormat:            "icu",
			PlaceholderFormatCustom: []string{"<.*?>", `\{.*?\}`},
		},
		MessageSet: project.MessageSet,
	}

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

	return data, nil
}
