package tpcc

import (
	"bytes"
	"database/sql"
	"fmt"
	"log"
	"os/exec"
)

type TpccConfig struct {
	TiDBCfg     *TiDBConfig
	Warehouse   int
	Connections int
	WarmupTime  int
	RunningTime int
	Interval    int
	ReportFile  string
}

type TiDBConfig struct {
	Host     string
	Port     int
	User     string
	Password string
	Database string
	CreateDB bool
	db       *sql.DB
}

func (t *TiDBConfig) createAndConnect() error {
	if t.CreateDB {
		db, err := sql.Open("mysql", fmt.Sprintf("%s:%s@tcp(%s:%d)/", t.User, t.Password, t.Host, t.Port))
		if err != nil {
			return err
		}
		defer db.Close()
		if _, err := db.Exec("DROP DATABASE IF EXISTS %s", t.Database); err != nil {
			return err
		}
		if _, err := db.Exec("CREATE DATABASE %s", t.Database); err != nil {
			return err
		}
	}

	var err error
	t.db, err = sql.Open("mysql", fmt.Sprintf("%s:%s@tcp(%s:%d)/%s", t.User, t.Password, t.Host, t.Port, t.Database))
	if err != nil {
		return err
	}

	return nil
}

func Prepare(t *TpccConfig) error {
	{
		if err := t.TiDBCfg.createAndConnect(); err != nil {
			return err
		}
		if _, err := t.TiDBCfg.db.Exec(schema); err != nil {
			return err
		}
		if _, err := t.TiDBCfg.db.Exec(fKey); err != nil {
			return err
		}
	}
	cmdStr := fmt.Sprintf("tpcc_load -h%s -P%d -d%s -u%s -p%s -w%d", t.TiDBCfg.Host, t.TiDBCfg.Port, t.TiDBCfg.Database, t.TiDBCfg.Password, t.Warehouse)
	log.Println("tpcc load data command: ", cmdStr)
	cmd := exec.Command("/bin/sh", "-c", cmdStr)
	if err := cmd.Run(); err != nil {
		return err
	}
	return nil
}

func Run(t *TpccConfig) (error, string) {
	cmdStr := fmt.Sprintf("tpcc_start -h%s -P%d -d%s -u%s -p%s -w%d -c%d -r%d -l%d -i%d", t.TiDBCfg.Host, t.TiDBCfg.Port, t.TiDBCfg.Database, t.TiDBCfg.Password, t.Warehouse, t.Connections, t.WarmupTime, t.RunningTime, t.Interval)
	log.Println("tpcc start command: ", cmdStr)
	cmd := exec.Command("/bin/sh", "-c", cmdStr)
	var out bytes.Buffer
	cmd.Stdout = &out
	if err := cmd.Run(); err != nil {
		return err, ""
	}
	return nil, out.String()
}
