package routers

import (
	"bytes"
	"fmt"
	"net/http"
	"research/pubgo"
	"research/xbdb"
	"strconv"
	"strings"
	"time"

	"github.com/syndtr/goleveldb/leveldb/iterator"
)

func Search(w http.ResponseWriter, req *http.Request) {
	w.Header().Set("Access-Control-Allow-Origin", "*") //同源策略，不加客户端调用不了。
	w.Header().Set("Content-Type", "application/json")
	pubgo.Tj.Brows("/Search/")

	params := getparas(req)
	tbname := "c"
	params["kw"] = Sublen(params["kw"], 35) //最大长度35
	Se := NewSeExefunc(tbname, params["kw"], params["dir"], 21)
	asc := params["asc"] == "" //params["asc"]默认空值即true
	p := params["p"]
	ok := false

	var key []byte
	var iter iterator.Iterator
	if p == "" {
		//第一页搜索没有p值，需要查询获得
		key = Table[tbname].Select.GetIdxPrefixLike([]byte("s"), []byte(Se.mkw))
		iter, ok = Table[tbname].Select.IterPrefixMove(key, asc)
	} else { //整型转byte留下的复制问题
		//《一人心念口言--14371||0
		ps := strings.Split(p, xbdb.Split)
		if len(ps) > 1 {
			p = strings.Replace(p, "whfgf", "?", -1) //url转义
			p = strings.Replace(p, "yhfgf", "&", -1) //url转义
			ips := strings.Split(ps[1], idssplit)    //将14371+0转为byte的字符串
			if len(ips) > 1 {
				aid, _ := strconv.Atoi(ips[0])
				sid, _ := strconv.Atoi(ips[1])
				ids := ArtSecToId(aid, sid)
				//pos, _ := strconv.Atoi(ps[2])
				//key = JoinBytes([]byte(ps[0]), []byte(xbdb.Split), []byte(ids), []byte(xbdb.Split), IntToBytes(pos))
				key = JoinBytes([]byte(ps[0]), []byte(xbdb.Split), []byte(ids))
				key = Table[tbname].Select.GetIdxPrefixLike([]byte("s"), key)
				iter, ok = Table[tbname].Select.IterSeekMove([]byte(key))
			} else {
				ok = false
				fmt.Println("错误的定位页p,ps：", p, ps)
				fmt.Println("kw=" + params["kw"])
			}
		} else {
			ok = false
			fmt.Println("错误的定位页p：", p)
		}

	}
	if !ok {
		//fmt.Printf("p: %v\n", p)
		//fmt.Println("kw=" + params["kw"])
		return
	}
	ts := pubgo.Newts() //计算执行时间
	Se.r.WriteString("{\"datalist\":[")
	xbdb.NewIters(iter, ok, asc, 0, -1).ForKVFun(Se.search)
	jsonstr := Se.r.String()
	jsonstr = strings.Trim(jsonstr, ",")
	Se.r.Reset()
	Se.r.WriteString(jsonstr)
	Se.r.WriteString("],")
	Se.r.WriteString("\"lastkey\":" + strconv.Quote(Se.lastkey) + ",")
	setime := ts.Gstrts()
	Se.r.WriteString("\"setime\":\"" + setime + "\",")
	//fmt.Printf("setime: %v\n", setime)
	Se.r.WriteString("\"count\":" + strconv.Itoa(Se.loop) + "}")
	w.Write(Se.r.Bytes())
	//w.Write([]byte(strconv.Quote(Se.r.String()))) //必须使用strconv.Quote转义
	Se.r.Reset()
	bufpool.Put(Se.r)
}


func (e *SeExefunc) search(k, v []byte) bool {

	if time.Since(e.bt).Seconds() > 3 { //只要是控制组合查询超时时间
		e.loop = 21 //以便用户点击下一页，分散时间进行搜索，缓解性能问题。
		//fmt.Println("组合查询超时3秒。") //多次执行由于会加载内存，则可以完成。
		return false
	}

	if !strings.Contains(string(k), e.mkw) {
		return false //key不存在kw，即已经超过所需数据
	}
	//rd := xbdb.KVToRd(k, v, []int{})
	//解构rd，转为字符串lastkey。参照artpost.ArtSecToId组合规则
	keys := Table[e.tbname].Split(k) //bytes.Split(rd, []byte(xbdb.Split))
	artid, secid := IdToArtSec(string(keys[2]))
	if artid == 0 {
		return true
	}
	if (e.artid == artid) && (e.secid == secid) { //排除重复。同一段落包含多个相同kw时，出现重复情况。
		return true
	}
	e.artid = artid
	e.secid = secid
	e.pos = xbdb.BytesToInt(keys[2])

	e.lastkey = string(keys[1]) + xbdb.Split + strconv.Itoa(e.artid) + idssplit + strconv.Itoa(e.secid)
	e.lastkey = strings.Replace(e.lastkey, "?", "whfgf", -1) //url转义 ?和&不能出现再url。
	e.lastkey = strings.Replace(e.lastkey, "&", "yhfgf", -1) //url转义 ?和&不能出现再url。

	e.cid = Artfid[uint32(e.artid)]   //获取文章对应的所属目录id
	if !CacaRand(int(e.cid), e.dir) { //范围搜索
		return true
	}
	if !e.exsit() { //组合查询
		return true
	}
	e.r.WriteString("{\"dir\":" + CRAMs.GetCaDirToJson(int(e.cid)) + ",") //写入目录路径
	e.r.WriteString(e.getartinfo() + ",")                                 //写入文章标题
	e.r.WriteString(e.getartmeta() + "},")                                //写入文章摘录信息
	e.loop++
	return e.loop < e.count
}
