package code

import (
	. "code.hoteas.com/golang/hotime/common"
	"code.hoteas.com/golang/hotime/db"
	"errors"
	"fmt"
	"io/ioutil"
	"net/http"
	"os"
	"path/filepath"
	"sort"
	"strings"
	"time"
)

type MakeCode struct {
	FileConfig    Map
	IndexMenus    Map
	TableConfig   Map
	TableColumns  map[string]map[string]Map
	SearchColumns map[string]map[string]Map
	Config        Map
	RuleConfig    []Map
	Error
}

func (that *MakeCode) Db2JSON(db *db.HoTimeDB, config Map) {
	isMake := false
	idSlice := Slice{}
	that.FileConfig = config
	if that.TableColumns == nil {
		that.TableColumns = make(map[string]map[string]Map)
	}
	if that.SearchColumns == nil {
		that.SearchColumns = make(map[string]map[string]Map)
	}

	//加载配置文件
	btes, err := ioutil.ReadFile(config.GetString("config"))

	that.Config = DeepCopyMap(Config).(Map)

	that.Config["name"] = config.GetString("table")
	if err == nil {
		cmap := Map{}
		//文件是否损坏
		cmap.JsonToMap(string(btes), &that.Error)
		for k, v := range cmap {
			that.Config[k] = v //程序配置
			//Config[k] = v      //系统配置
		}
	} else {
		that.Error.SetError(errors.New("config配置文件不存在，或者配置出错，使用缺省默认配置"))
	}
	//加载规则文件
	btesRule, errRule := ioutil.ReadFile(config.GetString("rule"))
	that.RuleConfig = []Map{}
	if errRule == nil {
		//cmap := Map{}
		//文件是否损坏
		ruleLis := ObjToSlice(string(btesRule), &that.Error)
		//cmap.JSON()
		for k, _ := range ruleLis {
			that.RuleConfig = append(that.RuleConfig, ruleLis.GetMap(k))
		}
	} else {
		for _, v := range ColumnNameType {
			that.RuleConfig = append(that.RuleConfig, Map{"name": v.Name, "list": v.List, "edit": v.Edit, "info": v.Info, "must": v.Must, "strict": v.Strict, "type": v.Type})
		}
		if db != nil {
			_ = os.MkdirAll(filepath.Dir(config.GetString("rule")), os.ModeDir)
			err = ioutil.WriteFile(config.GetString("rule"), []byte(ObjToStr(that.RuleConfig)), os.ModePerm)
			if err != nil {
				that.Error.SetError(err)
			}
		}

		that.Error.SetError(errors.New("rule配置文件不存在，或者配置出错，使用缺省默认配置"))
	}

	that.IndexMenus = Map{}
	menusConfig := that.Config.GetSlice("menus")
	//将配置写入到内存中仅作为判断用
	if menusConfig != nil {
		for kmenu, _ := range menusConfig {
			menu := menusConfig.GetMap(kmenu)
			if menu != nil {
				mname := menu.GetString("table")
				if mname == "" { //如果为空则不是表格
					mname = menu.GetString("name")
				}
				that.IndexMenus[mname] = menu
				childMenus := menu.GetSlice("menus")
				if childMenus != nil {
					for ckmenu, _ := range childMenus {
						cmenu := childMenus.GetMap(ckmenu)
						if cmenu != nil {
							cname := cmenu.GetString("table")
							if cmenu.GetString("table") == "" {
								continue
							}
							that.IndexMenus[mname+"/"+cname] = cmenu
						}

					}

				}

			}

		}
	}

	that.TableConfig = that.Config.GetMap("tables")
	if that.TableConfig == nil {
		that.TableConfig = Map{}
	}

	for tableName, _ := range that.TableConfig {

		columns := that.TableConfig.GetMap(tableName).GetSlice("columns")
		search := that.TableConfig.GetMap(tableName).GetSlice("search")
		//初始化
		if that.TableColumns[tableName] == nil {
			that.TableColumns[tableName] = map[string]Map{}
		}
		//初始化搜索项
		if that.SearchColumns[tableName] == nil {
			that.SearchColumns[tableName] = map[string]Map{}
		}

		//注入源数据
		for index, _ := range columns {
			columnsName := columns.GetMap(index).GetString("name")
			that.TableColumns[tableName][columnsName] = columns.GetMap(index)
		}

		//注入search源数据
		for index, _ := range search {
			searchName := search.GetMap(index).GetString("name")
			that.SearchColumns[tableName][searchName] = search.GetMap(index)
		}

	}

	if db == nil {

		return
	}

	//数据库反哺
	myInit := strings.Replace(InitTpt, "{{name}}", config.GetString("table"), -1)
	ctrList := ""

	nowTables := make([]Map, 0)
	if db.Type == "mysql" {
		nowTables = db.Select("INFORMATION_SCHEMA.TABLES", "TABLE_NAME as name,TABLE_COMMENT as label", Map{"TABLE_SCHEMA": db.DBName})
	}
	if db.Type == "sqlite" {
		nowTables = db.Select("sqlite_sequence", "name")
	}
	//idSlice=append(idSlice,nowTables)
	for _, v := range nowTables {
		if v.GetString("name") == "cached" {
			continue
		}
		if that.TableConfig.GetMap(v.GetString("name")) == nil {
			if v.GetString("label") == "" {
				v["label"] = v.GetString("name")
			}
			that.TableConfig[v.GetString("name")] = Map{
				"label":   v.GetString("label"),
				"table":   v.GetString("name"),
				"auth":    []string{"show", "add", "delete", "edit", "info"},
				"columns": []Map{},
				"search": []Map{

					{"type": "search", "name": "keyword", "label": "请输入关键词", "value": nil},
					{"type": "search", "name": "daterange", "label": "时间段", "value": nil},
					{"type": "search", "name": "sort", "label": "排序", "value": nil},
				},
			}
		}

		//初始化
		if that.TableColumns[v.GetString("name")] == nil {
			that.TableColumns[v.GetString("name")] = make(map[string]Map)
		}

		//初始化
		if that.SearchColumns[v.GetString("name")] == nil {
			that.SearchColumns[v.GetString("name")] = make(map[string]Map)
		}

		tableInfo := make([]Map, 0)
		if db.Type == "mysql" {
			tableInfo = db.Select("INFORMATION_SCHEMA.COLUMNS", "COLUMN_NAME AS name,COLUMN_TYPE AS type,COLUMN_COMMENT AS label", Map{"AND": Map{"TABLE_SCHEMA": db.DBName, "TABLE_NAME": v.GetString("name")}})
		}
		if db.Type == "sqlite" {
			tableInfo = db.Query("pragma table_info([" + v.GetString("name") + "]);")
		}

		idSlice = append(idSlice, tableInfo)
		for _, info1 := range tableInfo {
			info := DeepCopyMap(info1).(Map)
			if info.GetString("label") == "" {
				info["label"] = info.GetString("name")
			}
			coloum := that.TableColumns[v.GetString("name")][info.GetString("name")]

			if coloum == nil {
				//根据类型判断真实类型
				for k, v1 := range ColumnDataType {
					if strings.Contains(info.GetString("name"), k) || strings.Contains(info.GetString("type"), k) {
						info["type"] = v1
					}
				}

				coloum = Map{
					"name":  info.GetString("name"),
					"type":  info.GetString("type"),
					"label": info.GetString("label"),
					//"add":   false, "info": false, "edit": false, "list": true,
					//"must": false,
				}

				//备注以空格隔开，空格后的是其他备注
				indexNum := strings.Index(info.GetString("label"), " ")
				if indexNum > -1 {
					coloum["label"] = info.GetString("label")[:indexNum]
				}
				//去除数据信息，是用：号分割的
				indexNum = strings.Index(coloum.GetString("label"), ":")
				if indexNum > -1 {
					coloum["label"] = coloum.GetString("label")[:indexNum]
				}

				for _, ColumnName := range that.RuleConfig {
					if (ColumnName.GetBool("strict") && coloum.GetString("name") == ColumnName.GetString("name")) ||
						(!ColumnName.GetBool("strict") && strings.Contains(coloum.GetString("name"), ColumnName.GetString("name"))) {
						//全部都不需要则不加入
						if ColumnName.GetBool("edit") == false && ColumnName.GetBool("list") == false && ColumnName.GetBool("info") == false {
							coloum["notUse"] = true
							//continue
						}
						coloum["info"] = ColumnName.GetBool("info")
						coloum["edit"] = ColumnName.GetBool("edit")
						coloum["add"] = ColumnName.GetBool("edit")
						coloum["list"] = ColumnName.GetBool("list")
						coloum["must"] = ColumnName.GetBool("must")

						if ColumnName.GetBool("info") {
							delete(coloum, "info")
						}
						if ColumnName.GetBool("edit") {
							delete(coloum, "edit")
							delete(coloum, "add")
						}
						if ColumnName.GetBool("list") {
							delete(coloum, "list")
						}
						if !ColumnName.GetBool("must") {
							delete(coloum, "must")
						}

						if ColumnName.GetString("type") != "" {
							if ColumnName.GetString("type") == "time" && coloum["type"] == "number" {
								coloum["type"] = "unixTime"
							} else {
								coloum["type"] = ColumnName.GetString("type")
							}
						}
						if ColumnName.GetBool("strict") && coloum.GetString("name") == ColumnName.GetString("name") {
							break
						}

					}
				}

				//如果是select类型需要设置options
				if coloum.GetString("type") == "number" {
					coloum["sortable"] = true
				}

				//if !coloum.GetBool("notUse") {
				that.TableConfig.GetMap(v.GetString("name"))["columns"] = append(that.TableConfig.GetMap(v.GetString("name")).GetSlice("columns"), coloum)
				//}
				//如果是select类型需要设置options
				//if coloum.GetString("type") == "select" {

				options := Slice{}
				comments := strings.Split(info.GetString("label"), ":")
				if len(comments) >= 2 {
					optionComment := strings.Split(comments[1], ",")
					for _, v := range optionComment {
						optionSlice := strings.Split(v, "-")
						if len(optionSlice) >= 2 {
							options = append(options, Map{"name": optionSlice[1], "value": optionSlice[0]})
						}
					}
				}

				if coloum.GetString("type") == "select" {
					//coloum["must"] = true
					coloum["options"] = options
				} else if len(options) > 0 {
					//coloum["must"] = true
					coloum["options"] = options
					coloum["type"] = "select"

				}
				//}

			}
			//else {
			//
			//	//if !(coloum.GetString("label") != "备注" && info.GetString("label") == "备注") {
			//	//	coloum["label"] = info.GetString("label")
			//	//}
			//	//coloum["type"] = info.GetString("type")
			//}

			//暂时不关闭参数，保证表数据完全读取到
			that.TableColumns[v.GetString("name")][info.GetString("name")] = coloum

		}

		if config.GetInt("mode") != 0 {
			//创建模块文件
			//判断文件是否存在
			//_, err := os.OpenFile(name+"/"+v.GetString("name"), os.O_RDONLY, os.ModePerm)
			_, err := os.Stat(config.GetString("name") + "/" + v.GetString("name") + ".go")
			if err != nil { //文件不存在，则根据模板创建
				myCtr := strings.Replace(CtrTpt, "{{name}}", config.GetString("name"), -1)
				myCtr = strings.Replace(myCtr, "{{table}}", v.GetString("name"), -1)
				_ = os.MkdirAll(config.GetString("name"), os.ModeDir)
				err = ioutil.WriteFile(config.GetString("name")+"/"+v.GetString("name")+".go", []byte(myCtr), os.ModePerm)
				if err != nil {
					that.Error.SetError(err)
				}
				isMake = true
			}

			ctrList = ctrList + `"` + v.GetString("name") + `":` + v.GetString("name") + "Ctr,\r\n    "

		}

	}

	that.Config["tables"] = that.TableConfig

	//生成id，判断数据库是否有改变，以保证数据库和配置文件匹配唯一
	id := Md5(ObjToStr(idSlice))
	if id == that.Config.GetString("id") {
		if isMake { //有生成包文件
			fmt.Println("有新的业务代码生成，请重新运行")
			os.Exit(-1)
		}
		return
	}
	//数据生成完后进一步解析
	for fk, fv := range that.TableColumns {

		//判断是否将表写入menu中
		isMenusGet := false //判断是否被目录收录
		for indexKey, _ := range that.IndexMenus {
			indexCode := strings.Index(indexKey, fk)
			if indexCode == 0 || indexCode == 4 {
				isMenusGet = false
				continue
			}
			//如果相等或者表名在目录中已经设置（主要前一位是/并且他是最后一个字符串）
			if indexKey == fk || (indexCode != -1 && indexKey[indexCode-1] == '/' && indexKey[indexCode:] == fk) {
				isMenusGet = true
				break
			}
		}

		//目录没有收录
		if !isMenusGet {

			tablePrefixCode := strings.Index(fk, "_")
			isNewPrefix := false //假定表名没有前缀
			prefixName := ""
			//并且代表有前缀，根据数据表分库设定使用
			if tablePrefixCode != -1 {
				prefixName = fk[:tablePrefixCode]
			} else {
				prefixName = fk
			}
			//if tablePrefixCode != -1 {
			for ck, _ := range that.TableColumns {
				//判断不止一个前缀相同
				if (strings.Index(ck, prefixName) == 0 || strings.Index(prefixName, ck) == 4) && ck != fk {
					isNewPrefix = true
					break
				}
			}
			//}

			prefixName = DefaultMenuParentName + ":" + prefixName

			menuIns := Map{"label": that.TableConfig.GetMap(fk).GetString("label"), "table": fk}
			//多耗费一点内存
			mMenu := Map{"menus": Slice{menuIns}, "label": that.TableConfig.GetMap(fk).GetString("label"), "name": prefixName, "icon": "el-icon-setting"}
			//表名有前缀
			if !isNewPrefix {
				//是否已有对应前缀，已经有对应的menu只需要push进去即可
				prefixName = DefaultMenuParentName
				mMenu = Map{"menus": Slice{menuIns}, "label": "系统管理", "name": prefixName, "icon": "el-icon-setting"}
			}
			//没有新前缀
			if that.IndexMenus[prefixName] != nil {
				if that.IndexMenus[prefixName+"/"+fk] == nil {
					that.IndexMenus.GetMap(prefixName)["menus"] = append(that.IndexMenus.GetMap(prefixName).GetSlice("menus"), menuIns)
					that.IndexMenus[prefixName+"/"+fk] = menuIns
				} else {
					for k, v := range menuIns {
						that.IndexMenus.GetMap(prefixName + "/" + fk)[k] = v
					}
				}

			} else {

				that.Config["menus"] = append(that.Config.GetSlice("menus"), mMenu) //注入配置
				//写入Index
				that.IndexMenus[prefixName] = mMenu
				that.IndexMenus[prefixName+"/"+fk] = menuIns
			}
		}

		for k, v := range fv {

			//搜索服务
			if that.SearchColumns[fk][v.GetString("name")] == nil &&
				v.GetString("type") == "select" {
				search := that.TableConfig.GetMap(fk).GetSlice("search")
				sv := DeepCopyMap(v).(Map)
				sv["value"] = nil
				sv["options"] = append(sv.GetSlice("options"), Map{"name": "全部", "value": nil})
				that.TableConfig.GetMap(fk)["search"] = append(search, sv)
				that.SearchColumns[fk][k] = sv
			}

			//虚招后缀是_id结尾的表字段 假设org_id
			if len(k) <= 3 || strings.LastIndex(k, "_id") != len(k)-3 {
				continue
			}
			//普通表匹配 org_id匹配为org
			oldTableName := k[:len(k)-3]
			//上级ID匹配
			if oldTableName == "parent" {
				oldTableName = fk
			}
			//如果本身匹配则不再继续精简匹配
			if that.TableConfig[oldTableName] == nil {

				//如果依然找不到则查询system_org是否存在
				if that.TableConfig[DefaultMenuParentName+"_"+oldTableName] != nil {
					oldTableName = DefaultMenuParentName + "_" + oldTableName
				}

				//字段有动词前缀，自动进行解析
				prefixColumn := strings.Index(oldTableName, "_")

				//sys_org_id oldTableName即为sys此处判断为org表存在

				if prefixColumn > -1 && that.TableConfig[oldTableName[prefixColumn+1:]] != nil {
					oldTableName = oldTableName[prefixColumn+1:]
				}
				if prefixColumn >= len(oldTableName) {
					prefixColumn = -1
				}
				//如果依然找不到则查询system_org是否存在
				if prefixColumn > -1 && that.TableConfig[DefaultMenuParentName+"_"+oldTableName[prefixColumn+1:]] != nil {
					oldTableName = DefaultMenuParentName + "_" + oldTableName[prefixColumn+1:]
				}
			}

			//普通方式查询不到，则转换为大型项目模块划分,暂时只支持一级模块划分，
			//比如表sys_user 字段org_id，查询不到sys_org表则查询org表，org表查询不到则查询默认前缀system_org表
			//都查询不到则找不到，
			prefix := strings.Index(fk, "_")
			tableName := oldTableName
			if prefix > 0 {
				//表模块前缀sys_user sys即为前缀 sys_org
				tableName = fk[:prefix+1] + oldTableName
				if that.TableConfig[tableName] == nil || that.TableConfig[oldTableName] != nil {
					//不存在则改为org
					tableName = oldTableName
				}
				//表前缀+去除字段前缀
				prefixColumn := strings.Index(oldTableName, "_")
				if prefixColumn > -1 {
					tableName = fk[:prefix+1] + oldTableName[prefixColumn+1:]
					if that.TableConfig[tableName] == nil {
						tableName = oldTableName
					}
				}
			}

			//如果数据匹配则写入到配置中
			if that.TableConfig[tableName] != nil {
				v["link"] = tableName
				//一般查询name字段或者label字段，如果没有name字段则默认第二个地段
				if that.TableColumns[tableName]["name"] != nil {
					v["value"] = "name"
					continue
				}
				if that.TableColumns[tableName]["label"] != nil {
					v["value"] = "label"
					continue
				}
				tempC := that.TableConfig.GetMap(tableName).GetSlice("columns")
				isGet := true
				for k2, _ := range tempC {
					if strings.Contains(tempC.GetMap(k2).GetString("name"), "name") || strings.Contains(tempC.GetMap(k2).GetString("name"), "title") {
						v["value"] = tempC.GetMap(k2).GetString("name")
						isGet = false
						break
					}
				}

				if isGet && len(that.TableConfig.GetMap(tableName).GetSlice("columns")) > 2 {
					v["value"] = that.TableConfig.GetMap(tableName).GetSlice("columns").GetMap(1).GetString("name")
					continue
				}

			}

		}
	}

	//搜索增加树节点
	for fk, fv := range that.TableColumns {
		for k, v := range fv {
			if v.GetString("link") != "" && that.SearchColumns[fk][k] == nil &&
				that.TableColumns[v.GetString("link")]["parent_id"] != nil {
				//搜索服务
				search := that.TableConfig.GetMap(fk).GetSlice("search")
				sv := Map{"type": "tree", "label": v["label"], "name": v["name"], "value": v["value"], "link": v["link"]}
				that.TableConfig.GetMap(fk)["search"] = append(search, sv)

				that.SearchColumns[fk][k] = sv
			}
		}
	}

	fmt.Println(id, "---", that.Config.GetString("id"))
	that.Config["id"] = id

	if config.GetInt("mode") != 0 {
		//init文件初始化
		myInit = strings.Replace(myInit, "{{id}}", id, -1)
		myInit = strings.Replace(myInit, "{{tablesCtr}}", ctrList, -1)
		_ = os.MkdirAll(config.GetString("name"), os.ModeDir)
		err = ioutil.WriteFile(config.GetString("name")+"/init.go", []byte(myInit), os.ModePerm)
		if err != nil {
			that.Error.SetError(err)
		}
	}

	//写入配置文件
	//err = json.Indent(&configByte, []byte(that.Config.ToJsonString()), "", "\t")
	_ = os.MkdirAll(filepath.Dir(config.GetString("config")), os.ModeDir)
	err = ioutil.WriteFile(config.GetString("config"), []byte(that.Config.ToJsonString()), os.ModePerm)
	if err != nil {
		that.Error.SetError(err)
	}

	fmt.Println("有新的代码生成，请重新运行")
	os.Exit(-1)

}

func (that *MakeCode) Info(table string, userData Map, db *db.HoTimeDB) (string, Map) {
	reStr := ""
	data := Map{}
	var ruleData Map
	testQu := []string{}
	testQuData := that.TableColumns[table]
	for key, _ := range testQuData {
		//fmt.Println(key, ":", value)
		testQu = append(testQu, key)
	}
	sort.Strings(testQu)

	for _, k := range testQu {
		v := testQuData[k]
		if v == nil {
			continue
		}
		//准备加入索引权限
		if v.GetString("link") != "" &&
			userData != nil &&
			that.TableColumns[v.GetString("link")]["parent_id"] != nil {
			//初始化ruleData
			if ruleData == nil {
				ruleData = Map{}
				for _, v := range that.TableColumns[that.FileConfig.GetString("table")] {
					if v.GetString("link") != "" &&
						v.GetString("name") != "parent_id" &&
						userData.Get(v.GetString("name")) != nil {
						ruleData[v.GetString("link")] = userData.Get(v.GetString("name"))
					}
				}
			}
			if ruleData[v.GetString("link")] != nil {

				if v.GetString("name") == "parent_id" {
					data["index[~]"] = "," + ruleData.GetString(v.GetString("link")) + ","

				} else {
					idMap := db.Select(v.GetString("link"), "id", Map{"index[~]": "," + ruleData.GetString(v.GetString("link")) + ","})
					ids := Slice{ruleData.GetCeilInt(v.GetString("link"))}
					for _, v := range idMap {
						ids = append(ids, v.GetCeilInt("id"))
					}
					data[v.GetString("name")] = ids
				}

			}
		}

		if v.Get("info") == nil || v.GetBool("info") {
			reStr += "`" + v.GetString("name") + "`,"
		}
	}
	if len(reStr) != 0 {
		reStr = reStr[:len(reStr)-1]
	}
	return reStr, data
}
func (that *MakeCode) Add(table string, user Map, req *http.Request) Map {
	data := Map{}
	for _, v := range that.TableColumns[table] {
		//不可使用，未在前端展示，但在内存中保持有
		if v.GetBool("notUse") {
			if v.GetString("type") == "index" && that.TableColumns[table]["parent_id"] != nil {
				data[v.GetString("name")] = ","
			}

			continue
		}
		if v.Get("add") == nil || v.GetBool("add") {

			if len(req.Form[v.GetString("name")]) == 0 {

				if user[v.GetString("name")] != nil {
					data[v.GetString("name")] = user[v.GetString("name")]
					continue
				}

				if that.FileConfig.GetString("table")+"_id" == v.GetString("name") {
					data[v.GetString("name")] = user["id"]
					continue
				}

				if v.GetBool("must") {
					return nil
				} else {
					continue
				}

			}
			reqValue := req.FormValue(v.GetString("name"))
			if (reqValue == "" || reqValue == "null") && strings.Contains(v.GetString("name"), "id") {
				data[v.GetString("name")] = nil
			} else {
				if v.GetString("type") == "password" {
					data[v.GetString("name")] = Md5(reqValue)
				} else {
					data[v.GetString("name")] = reqValue
				}

			}
		}

		if v.GetString("name") == "create_time" {
			if v.GetString("type") == "unixTime" {
				data[v.GetString("name")] = time.Now().Unix()
			}
			if v.GetString("type") == "time" {
				data[v.GetString("name")] = time.Now().Format("2006-01-02 15-04-05")
			}
			continue
		}

		if v.GetString("name") == "modify_time" {
			if v.GetString("type") == "unixTime" {
				data[v.GetString("name")] = time.Now().Unix()
			}
			if v.GetString("type") == "time" {
				data[v.GetString("name")] = time.Now().Format("2006-01-02 15-04-05")
			}
		}
	}
	if len(data) == 0 {
		return nil
	}

	return data
}
func (that *MakeCode) Edit(table string, req *http.Request) Map {
	data := Map{}
	for _, v := range that.TableColumns[table] {
		//不可使用，未在前端展示，但在内存中保持有
		if v.GetBool("notUse") {
			if v.GetString("type") == "index" && that.TableColumns[table]["parent_id"] != nil {
				data[v.GetString("name")] = ","
			}
			continue
		}

		if v.Get("edit") == nil || v.GetBool("edit") {
			reqValue := req.FormValue(v.GetString("name"))
			if reqValue == "" || reqValue == "null" {
				continue
			}
			if v.GetString("type") == "password" {
				data[v.GetString("name")] = Md5(reqValue)
			} else {
				data[v.GetString("name")] = reqValue
			}
		}
		if v.GetString("name") == "modify_time" {
			data[v.GetString("name")] = time.Now().Unix()
		}
	}

	if len(data) == 0 {
		return nil
	}

	return data
}
func (that *MakeCode) Delete(table string, req *http.Request) Map {
	data := Map{}
	for _, v := range that.TableColumns[table] {
		//不可使用，未在前端展示，但在内存中保持有
		if v.GetBool("notUse") {
			if v.GetString("type") == "index" && that.TableColumns[table]["parent_id"] != nil {
				data[v.GetString("name")] = ","
			}
			continue
		}

	}
	return data
}

func (that *MakeCode) Search(table string, userData Map, req *http.Request, db *db.HoTimeDB) (string, Map, Map) {
	reStr := ""
	leftJoin := Map{}
	data := Map{}
	keyword := Map{}
	daterange := Map{}
	sortMap := Map{}
	var ruleData Map
	hasUser := false

	keywordStr := req.FormValue("keyword")

	testQu := []string{}
	testQuData := that.TableColumns[table]
	for key, _ := range testQuData {
		//fmt.Println(key, ":", value)
		testQu = append(testQu, key)
	}
	sort.Strings(testQu)

	for _, k := range testQu {
		v := testQuData[k]
		//不可使用，未在前端展示，但在内存中保持有
		if v.GetBool("notUse") {

			continue
		}
		if v["list"] != false {

			if v.GetString("link") != "" &&
				v.GetString("name") != "parent_id" {

				reStr += table + "." + v.GetString("name") + "," +
					v.GetString("link") + "." + v.GetString("value") + " AS " +
					v.GetString("link") + "_" + v.GetString("name") + "_" + v.GetString("value") + ","

				if v.GetString("value") == "name" && that.TableColumns[v.GetString("link")]["nickname"] != nil {
					reStr += v.GetString("link") + ".nickname AS " +
						v.GetString("link") + "_" + v.GetString("name") + "_nickname,"
				}

				if that.TableColumns[v.GetString("link")]["phone"] != nil {
					reStr += v.GetString("link") + ".phone AS " +
						v.GetString("link") + "_" + v.GetString("name") + "_phone,"
				}

				leftJoin["[>]"+v.GetString("link")] =
					table + "." + v.GetString("name") + "=" +
						v.GetString("link") + ".id"
				if v.GetString("link") == "admin" {
					hasUser = true
				}

				reqValue := req.FormValue(v.GetString("name"))
				if reqValue != "" {
					data[table+"."+v.GetString("name")] = reqValue
				}

			} else {
				reStr += table + "." + v.GetString("name") + ","
			}

			//准备加入索引权限
			if v.GetString("link") != "" &&
				userData != nil &&
				that.TableColumns[v.GetString("link")]["parent_id"] != nil {
				//初始化ruleData
				if ruleData == nil {
					ruleData = Map{}
					for _, v := range that.TableColumns[that.FileConfig.GetString("table")] {
						if v.GetString("link") != "" &&
							v.GetString("name") != "parent_id" &&
							userData.Get(v.GetString("name")) != nil {
							ruleData[v.GetString("link")] = userData.Get(v.GetString("name"))
						}
					}
				}
				if ruleData[v.GetString("link")] != nil {

					if v.GetString("name") == "parent_id" {
						data[table+".index[~]"] = "," + ruleData.GetString(v.GetString("link")) + ","

					} else {
						idMap := db.Select(v.GetString("link"), "id", Map{"index[~]": "," + ruleData.GetString(v.GetString("link")) + ","})
						ids := Slice{ruleData.GetCeilInt(v.GetString("link"))}
						for _, v := range idMap {
							ids = append(ids, v.GetCeilInt("id"))
						}
						data[table+"."+v.GetString("name")] = ids
					}

				}

			}

			if keywordStr != "" {
				if v.GetString("type") == "text" {
					keyword[table+"."+v.GetString("name")+"[~]"] = keywordStr

				}
				if v.GetString("name") == "id" {
					keyword[table+"."+v.GetString("name")] = keywordStr
				}
				if v.GetString("link") != "" &&
					v.GetString("name") != "parent_id" {
					childs := db.Select(v.GetString("link"), "id", Map{v.GetString("value") + "[~]": keywordStr})
					childIds := Slice{}
					for _, cv := range childs {
						childIds = append(childIds, cv.GetString("id"))
					}
					if len(childIds) != 0 {
						keyword[v.GetString("link")+".id"] = childIds
					}

				}
			}

		}
	}
	if len(reStr) != 0 {
		reStr = reStr[:len(reStr)-1]
	}

	search := that.TableConfig.GetMap(table).GetSlice("search")
	for k, _ := range search {

		reqValue := req.FormValue(search.GetMap(k).GetString("name"))
		if reqValue == "" {
			continue
		}
		searchItem := search.GetMap(k)
		searchItemName := searchItem.GetString("name")

		//columns := that.TableConfig.GetMap(table).GetSlice("columns")
		if searchItem.GetString("type") == "search" {
			for _, v := range that.TableColumns[table] {
				if v["list"] == false {
					continue
				}
				//日期类型
				if searchItemName == "daterange" {
					if v.GetString("type") == "unixtime" {
						//fmt.Println(req.Form["daterange"])
						if len(req.Form["daterange"]) == 1 {
							daterange[table+"."+v.GetString("name")+"[<]"] = req.FormValue("daterange")
						} else if len(req.Form["daterange"]) == 2 {

							daterange[table+"."+v.GetString("name")+"[<>]"] = ObjToSlice(req.Form["daterange"])
						}
					}
					if v.GetString("type") == "time" {
						//fmt.Println(req.Form["daterange"])

						if len(req.Form["daterange"]) == 1 {
							t := time.Unix(ObjToCeilInt64(req.FormValue("daterange")), 0).Format("2006-01-02 15:04:05")

							daterange[table+"."+v.GetString("name")+"[<]"] = t

						} else if len(req.Form["daterange"]) == 2 {
							t1 := time.Unix(ObjToCeilInt64(req.Form["daterange"][0]), 0).Format("2006-01-02 15:04:05")
							t2 := time.Unix(ObjToCeilInt64(req.Form["daterange"][1]), 0).Format("2006-01-02 15:04:05")
							daterange[table+"."+v.GetString("name")+"[<>]"] = Slice{t1, t2}
						}
					}

				}
			}

			if searchItem.GetString("name") == "sort" {
				sortMap["ORDER"] = table + "." + reqValue
			}

			continue
		}
		//树节点模式搜索
		if searchItemName == "parent_id" {
			parentID := ObjToInt(req.FormValue("parent_id"))
			if parentID == 0 {
				parentID = userData.GetCeilInt(table + "_id")
				data["OR"] = Map{table + ".id": parentID, table + ".parent_id": nil}
			} else {
				data[table+".parent_id"] = parentID
			}
			continue
		}

		data[table+"."+searchItemName] = reqValue

	}
	if sortMap["ORDER"] == nil {
		sortMap["ORDER"] = table + ".id DESC"
	}

	where := Map{}

	if len(keyword) == 1 {
		for k, v := range keyword {
			data[k] = v
		}
	}
	if len(keyword) > 1 {
		if data["OR"] != nil {
			data = Map{"AND": data, "OR": keyword}
		} else {
			data["OR"] = keyword
		}

	}

	if len(daterange) == 1 {
		for k, v := range daterange {
			data[k] = v
		}
	}

	if len(daterange) > 1 {
		if data == nil || len(data) == 0 {
			data = Map{"OR": daterange}
		} else {
			data = Map{"AND": Map{"AND": data, "OR": daterange}}
		}
	}

	if len(data) > 1 {
		where["AND"] = data
	}

	if len(data) == 1 {
		where = data
	}

	if len(where) == 0 && hasUser {

		//where["admin.id"] = userData["id"]

	}

	if len(sortMap) != 0 {
		for k, v := range sortMap {
			where[k] = v
		}
	}

	return reStr, leftJoin, where
}

func setListener() {

}
