package command

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

	"github.com/juju/errors"
	"github.com/ngaut/log"
	"github.com/pingcap/schrodinger/pkg/types"
)

func saveDumpFile(data interface{}, dataDir, filePrefix, format string) {
	switch format {
	case "json":
		// TODO: split files according to file size
		if err := saveToJSON(data, fmt.Sprintf("%s/%s.json", dataDir, filePrefix)); err != nil {
			ExitWithError(ExitError, err)
		}
	default:
		ExitWithError(ExitBadArgs, errors.Errorf("data format %s not supported", format))
	}
}

func saveToJSON(data interface{}, file string) error {
	jsonData, err := json.Marshal(data)
	if err != nil {
		return errors.Trace(err)
	}

	return errors.Trace(ioutil.WriteFile(file, jsonData, 0644))
}

func readTestTemplatesFromJSONFile(dir string, filePrefix string) (types.TestTemplates, error) {
	var tests types.TestTemplates

	err := filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
		if !info.IsDir() && strings.HasPrefix(info.Name(), filePrefix) {
			data, err := ioutil.ReadFile(path)
			if err != nil {
				return errors.Trace(err)
			}

			var tmpTests types.TestTemplates
			if err = json.Unmarshal(data, &tmpTests); err != nil {
				return errors.Trace(err)
			}

			tests = append(tests, tmpTests...)
		}

		return nil
	})

	if err != nil {
		return nil, errors.Trace(err)
	}

	return tests, nil
}

func readConfigTemplatesFromJSONFile(dir string, filePrefix string) (types.TiDBClusterConfigTemplates, error) {
	var cts types.TiDBClusterConfigTemplates

	err := filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
		if !info.IsDir() && strings.HasPrefix(info.Name(), filePrefix) {
			data, err := ioutil.ReadFile(path)
			if err != nil {
				return errors.Trace(err)
			}

			var ct types.TiDBClusterConfigTemplates
			if err = json.Unmarshal(data, &ct); err != nil {
				return errors.Trace(err)
			}

			cts = append(cts, ct...)
		}

		return nil
	})

	if err != nil {
		return nil, errors.Trace(err)
	}

	return cts, nil
}

func readBoxesFromJSONFile(dir string, filePrefix string) (types.Boxes, error) {
	var boxes types.Boxes

	err := filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
		if !info.IsDir() && strings.HasPrefix(info.Name(), filePrefix) {
			data, err := ioutil.ReadFile(path)
			if err != nil {
				return errors.Trace(err)
			}

			var box types.Boxes
			if err = json.Unmarshal(data, &box); err != nil {
				log.Error(err)
				return errors.Trace(err)
			}

			boxes = append(boxes, box...)
		}

		return nil
	})

	if err != nil {
		return nil, errors.Trace(err)
	}

	return boxes, nil
}
