package main

import (
	"flag"
	"fmt"
	"os"
	"os/signal"
	"strings"
	"syscall"

	"github.com/pingcap/errors"
	"github.com/pingcap/schrodinger-test/dmctl"
	"github.com/pingcap/schrodinger-test/tpcc"
	"github.com/pingcap/schrodinger-test/util"
	"github.com/pingcap/schrodinger/pkg/test_client"
	"github.com/pingcap/schrodinger/pkg/types"
	"golang.org/x/net/context"
)

var (
	warehouse int
	useDM     bool
)

const (
	defWarehouse = 10
	defUseDM     = false
)

func init() {
	flag.IntVar(&warehouse, "warehouse", defWarehouse, fmt.Sprintf("number of warehouse (default %d)", defWarehouse))
	flag.BoolVar(&useDM, "dm", defUseDM, fmt.Sprintf("test DM if true (default %v)", defUseDM))
}

func main() {
	flag.Parse()

	ctx, cancel := context.WithCancel(context.Background())
	cli := client.New(ctx, client.ModeOnline)

	sc := make(chan os.Signal, 1)
	signal.Notify(sc,
		syscall.SIGHUP,
		syscall.SIGINT,
		syscall.SIGTERM,
		syscall.SIGQUIT)

	go func() {
		sig := <-sc
		client.Infof("[tpcc] Got signal [%d] to exit.", sig)
		cancel()
		os.Exit(0)
	}()

	var err error
	inputDSN := ""
	outputDSN := fetchDSN(cli)
	client.Infof("[tpcc] config: %s", outputDSN)
	if useDM {
		inputDSN, err = configDM(cli)
		if err != nil {
			client.Fatalf("[tpcc] return with error %s", err)
			os.Exit(1)
		}
	} else {
		inputDSN = outputDSN
	}
	if err = tpcc.NewTPCCCase(inputDSN, outputDSN, warehouse).Execute(); err != nil {
		client.Fatalf("[tpcc] return with error %s", err)
		os.Exit(1)
	}
}

func fetchDSN(cli *client.Client) string {
	tidbAddr := strings.Split(cli.TiDBService(), ":")
	tidbIP, tidbPort := tidbAddr[0], tidbAddr[1]
	tidbDSN := fmt.Sprintf("%s:%s", tidbIP, tidbPort)
	return tidbDSN
}

func configDM(cli *client.Client) (string, error) {
	master, deploys, err := util.SetUpDM(cli, 1, types.MysqlType, "5.7", "")
	if err != nil {
		return "", errors.Trace(err)
	}
	dmMasterCtl, err := dmctl.CreateDMMasterCtl(master)
	if err != nil {
		return "", errors.Trace(err)
	}
	// TODO: add a real config
	err = dmMasterCtl.StartTask(context.TODO(), "", []string{deploys[0].DmWorker})
	if err != nil {
		return "", errors.Trace(err)
	}
	return deploys[0].MysqlInstance, nil
}
