package main

import "strings"

type SDInfo struct {
	SchemasFilter map[string]int
	Schemas       []SDSchema
	IC            bool
}

func (i *SDInfo) AddDBTable(db, tbl string) {
	db = strings.TrimSpace(db)
	tbl = strings.TrimSpace(tbl)
	if len(db) == 0 {
		return
	}
	db_l := i.cv(db)
	tbl_l := i.cv(tbl)

	idx, ok := i.SchemasFilter[db_l]
	if !ok {
		idx = len(i.Schemas)
		i.SchemasFilter[db_l] = idx
		i.Schemas = append(i.Schemas, SDSchema{
			Schema:       db,
			TablesFilter: map[string]int{},
		})
	}
	if len(tbl_l) > 0 {
		schema := &i.Schemas[idx]
		idx2, ok := schema.TablesFilter[tbl_l]
		if !ok {
			idx2 = len(schema.Tables)
			schema.TablesFilter[tbl_l] = idx2
			schema.Tables = append(schema.Tables, SDTable{
				tbl,
			})
		}
	}
}

func (i *SDInfo) cv(s string) string {
	s = strings.TrimSpace(s)
	if i.IC {
		return strings.ToLower(s)
	}
	return s
}

type SDSchema struct {
	Schema       string
	TablesFilter map[string]int
	Tables       []SDTable
}

type SDTable struct {
	Name string
}

type DBInfo struct {
	Host     string
	Port     string
	User     string
	Password string
	TidbStat string
}

func parseConfig() {
	str := strings.TrimSpace(*dbs)
	info.IC = *ignorecase
	if len(str) > 0 {
		arr := strings.Split(str, ",")
		for _, db := range arr {
			info.AddDBTable(db, "")
		}
	}
	//
	str = strings.TrimSpace(*tables)
	if len(str) > 0 {
		arr := strings.Split(str, ",")
		for _, tbl := range arr {
			tbl = strings.TrimSpace(tbl)
			if len(tbl) == 0 {
				continue
			}
			a2 := strings.Split(tbl, ".")
			if len(a2) != 2 {
				LogFatal("Table name (database.table) format error .Pleas type '-h' for help info.")
			}
			// a.b,.,a.c  --> a.b,a.c ，空自动过滤掉.
			info.AddDBTable(a2[0], a2[1])
		}
	}
}

var dbFilter = []string{"INFORMATION_SCHEMA", "PERFORMANCE_SCHEMA", "mysql", "default"}

func doDBConnectors() {
	dbInfo.Password = *pwd
	dbInfo.User = *user
	dbInfo.TidbStat = strings.TrimSpace(*tidbStat)
	str := strings.TrimSpace(*addr)
	if len(str) > 0 {
		arr := strings.Split(str, ":")
		if len(arr) != 2 {
			LogFatal("Database address format err. Pleas type '-h' for help info.")
		}
		dbInfo.Host = strings.TrimSpace(arr[0])
		dbInfo.Port = strings.TrimSpace(arr[1])
	}
	dbobj := newMysql(dbInfo)
	dbobj.Close()
}

func addDBFilter(in string) {
	in = strings.TrimSpace(in)
	if len(in) == 0 {
		return
	}
	for _, db := range dbFilter {
		if *ignorecase {
			if strings.EqualFold(in, db) {
				return
			}
		} else {
			if in == db {
				return
			}
		}
	}
	dbFilter = append(dbFilter, in)
	LogInfo("addDBFilter(%s)", in)
}

func filterDb(in string) bool {
	in = strings.TrimSpace(in)
	for _, db := range dbFilter {
		if *ignorecase {
			if strings.EqualFold(in, db) {
				return true
			}
		} else {
			if in == db {
				return true
			}
		}
	}
	return false
}

func prepareInfo() {
	if len(*filter) > 0 {
		arr := strings.Split(*filter, ",")
		for _, f := range arr {
			addDBFilter(f)
		}
	}
	if len(info.Schemas) == 0 {
		// load all schemas .
		schemas, err := getAllSchema(newMysql(dbInfo))
		if err != nil {
			LogFatal("getAllSchema err:%s", err.Error())
		}
		for _, db := range schemas {
			if filterDb(db) {
				continue
			}
			info.AddDBTable(db, "")
		}
	}
	for _, s := range info.Schemas {
		if len(s.Tables) > 0 {
			continue
		}
		// if empty; load all tables;
		obj := newMysql(dbInfo)
		tbls, err := getAllTablesBySchema(obj, s.Schema)
		if err != nil {
			LogFatal("getAllTablesBySchema(%s) err:%s", s.Schema, err.Error())
		}
		for _, tbl := range tbls {
			info.AddDBTable(s.Schema, tbl)
		}
	}
}
