package main

import (
	"context"
	"database/sql"
	"fmt"
	_ "github.com/go-sql-driver/mysql"
	"io/ioutil"
	"net/http"
	"time"
)

var (
	filter_dbs = []string{"INFORMATION_SCHEMA", "PERFORMANCE_SCHEMA", "mysql", "default"}
)

func newMysql(info DBInfo) *sql.DB {
	dns := fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?charset=utf8&parseTime=True", info.User, info.Password, info.Host, info.Port, "")
	dbo, err := sql.Open("mysql", dns)
	if err != nil {
		LogFatal("connect mysql(%s) error:%s.", dns, err.Error())
	}
	timeout, cancel := context.WithTimeout(context.TODO(), 3*time.Second)
	err = dbo.PingContext(timeout)
	if err != nil {
		cancel()
		LogFatal("connect mysql(%s) error:%s.", dns, err.Error())
	}
	cancel()
	return dbo
}

func getAllSchema(obj *sql.DB) (ret []string, err error) {
	return getAllItems(obj, "show databases")
}

func getAllItems(obj *sql.DB, sql string) (ret []string, err error) {
	rows, err := obj.Query(sql)
	if err != nil {
		return nil, err
	}
	var str string
	for rows.Next() {
		err = rows.Scan(&str)
		if err != nil {
			return nil, err
		}
		ret = append(ret, str)
	}
	return ret, nil
}

func getAllTablesBySchema(obj *sql.DB, db string) ([]string, error) {
	sql := fmt.Sprintf("show tables IN %s", db)
	return getAllItems(obj, sql)
}

type ShowValue struct {
	Name string
	SQL  string
}

func getShowCreate(obj *sql.DB, sql string) (sv ShowValue, err error) {
	row := obj.QueryRow(sql)
	err = row.Scan(&sv.Name, &sv.SQL)
	return
}

func makeStatsUrl(addr, schema, table string) string {
	return fmt.Sprintf("http://%s/stats/dump/%s/%s", addr, schema, table)
}

func getStatusDump(addr, schema, table string) ([]byte, error) {
	resp, err := http.Get(makeStatsUrl(addr, schema, table))
	if err != nil {
		return nil, fmt.Errorf("getStatus(%s.%s) http err:%s", schema, table, err.Error())
	}
	if resp.StatusCode != http.StatusOK {
		return nil, fmt.Errorf("getStatus(%s.%s) http status err:%s-%s", schema, table, resp.Status, http.StatusText(resp.StatusCode))
	}
	d, err := ioutil.ReadAll(resp.Body)
	resp.Body.Close()
	if err != nil {
		return nil, fmt.Errorf("getStatus(%s.%s) http read err:%s", schema, table, err.Error())
	}
	return d, nil
}

func getTidbVersion(obj *sql.DB) (str string, err error) {
	row := obj.QueryRow("select tidb_version()")
	err = row.Scan(&str)
	return str, err
}
