package api

import (
	"encoding/json"
	"io"
	"io/ioutil"
	"math/rand"
	"sort"
	"strconv"
	"strings"

	"github.com/juju/errors"
	"github.com/ngaut/log"
	"github.com/pingcap/wormhole/pkg/whpb"
)

func readJSON(r io.ReadCloser, data interface{}) error {
	defer r.Close()

	b, err := ioutil.ReadAll(r)
	if err != nil {
		return errors.Trace(err)
	}
	err = json.Unmarshal(b, data)
	return errors.Trace(err)
}

func computeReplicate(partitionNums int32, tableNum int) int32 {
	return int32((int(partitionNums)*tableNum+(splitJobFactor-1))/splitJobFactor) + 1
}

// IDs represents ids set
type IDs []uint64

func (ids IDs) Len() int           { return len(ids) }
func (ids IDs) Swap(i, j int)      { ids[i], ids[j] = ids[j], ids[i] }
func (ids IDs) Less(i, j int) bool { return ids[i] < ids[j] }

func toGroupLabels(ids IDs) []string {
	sort.Sort(ids)

	workers := make([]string, len(ids))
	for i, id := range ids {
		workers[i] = strconv.FormatUint(id, 10)
	}

	return workers
}

func fromGroupLabels(labels []string) ([]uint64, error) {
	ids := make([]uint64, len(labels))

	for i, idStr := range labels {
		id, err := strconv.ParseUint(idStr, 10, 64)
		if err != nil {
			return nil, errors.Trace(err)
		}
		ids[i] = id
	}

	return ids, nil
}

func formatJobStatus(jobs []*whpb.Job) ([]*whpb.JobStatus, error) {
	jss := make([]*whpb.JobStatus, 0, len(jobs))
	for _, job := range jobs {
		jss = append(jss, job.GetStatus())
	}
	return jss, nil
}

func validateDB(db whpb.DBAccount) error {
	if strings.TrimSpace(db.GetHost()) == "" {
		return errors.New("[ether] DB host is empty")
	}

	if db.GetPort() == 0 {
		return errors.New("[ether] DB port is empty")
	}

	if strings.TrimSpace(db.GetUsername()) == "" {
		return errors.New("[ether] DB username is empty")
	}

	return nil
}

func validateServerID(serverid int32) int32 {
	if serverid == 0 {
		log.Warn("server id is 0, will use rand number as serverid")
		baseid := 1000
		return int32(baseid + rand.Intn(1000))
	}

	return serverid
}
