package recordview

import (
	"bytes"
	"dbweb/core"
	"dbweb/lib/lsession"
	"dbweb/lib/tempext"
	"encoding/gob"
	"encoding/json"
	"net/url"

	"github.com/linlexing/dbx/ddb"

	"github.com/linlexing/dbx/common"
	"github.com/linlexing/dbx/pageselect"

	"text/template"
)

//ParseParam 解开传递的参数
func ParseParam(bys []byte, user *core.User) *RecordViewParam {
	var r RecordViewParam
	if err := json.Unmarshal(bys, &r); err != nil {
		core.LOG.Panic(string(bys) + "\n" + err.Error())
	}
	r.user = user
	for _, one := range r.Processes {
		one.param = &r
	}
	return &r
}

//GetCallParam 从一个url地址中获取调用的参数
func GetCallParam(p *core.ElementHandleArgs) *ProcessParam {
	pam, ok := p.LSession.Get(p.Req.URL.Query().Get("_rvp")).(*ProcessParam)
	if !ok {
		return nil
	}
	pam.user = p.User
	pam.Select.p = p
	return pam
}

//BuildRecordViewURL 构造一个调用其他工作元素的url，注意more参数的传递，该参数一直传递到底层的按钮中
func BuildRecordViewURL(eleName, title, condition string, more []string, user *core.User) string {
	u, _ := url.Parse("/" + eleName)
	q := u.Query()
	q.Set("_tq_title", user.EncodeQueryValue(title))
	q.Set("_tq_condition", user.EncodeQueryValue(condition))
	if len(more) > 0 {
		bys := bytes.NewBuffer(nil)
		if err := gob.NewEncoder(bys).Encode(more); err != nil {
			core.LOG.Panic(err)
		}
		q.Set("_more", user.EncodeQueryValueB(bys.Bytes()))
	}

	u.RawQuery = q.Encode()
	return u.String()
}

//MustCountRecordView 统计一个查询的记录数，可传入附加条件，出错则异常
func MustCountRecordView(db ddb.DB, eleName, condition string, more []string, user *core.User, lsession *lsession.Session) int64 {
	if i, err := CountRecordView(db, eleName, condition, more, user, lsession); err != nil {
		core.LOG.Panic(err)
		return 0
	} else {
		return i
	}
}

//CountRecordView 统计一个查询的记录数，可传入附加条件，返回错误
func CountRecordView(db ddb.DB, eleName, condition string, more []string, user *core.User, lsession *lsession.Session) (int64, error) {
	ele := core.LoadElement(db, eleName)
	param := ParseParam(ele.Params, user)
	dataDB := core.LoadOuterDB(db, param.DB)
	sqlSelect := pageselect.NewPageSelect(param.Sql, param.AllColumns, param.ManualPage)
	if more == nil {
		more = []string{}
	}
	sqlSelect.SQLRenderArgs = map[string]interface{}{
		"Driver":   db.DriverName(),
		"User":     user,
		"LSession": lsession,
		"More":     more,
	}
	if len(condition) > 0 {
		sqlSelect.Conditions = []*pageselect.SQLCondition{
			&pageselect.SQLCondition{
				Name:      "add",
				PlainText: condition,
			},
		}
	}
	strSQL, err := sqlSelect.BuildRowCountSQL(dataDB.DriverName())
	if err != nil {
		return -1, err
	}
	var rcount int64
	err = dataDB.QueryRow(strSQL).Scan(&rcount)
	if err != nil {
		return -1, common.NewSQLError(err, strSQL)
	}
	return rcount, nil

}

//处理单个query值，采用aes加密算法
func transQueryValue(tmpl string, row map[string]interface{}, user *core.User) string {
	//由于nil值，在模板中会出现<no value>，所以要转换成""
	trow := map[string]interface{}{}
	for k, v := range row {
		if v == nil {
			trow[k] = ""
		} else {
			trow[k] = v
		}
	}
	t, err := template.New("query").Funcs(tempext.GetFuncMap()).Parse(tmpl)
	if err != nil {
		core.LOG.Panic(err)
	}

	out := bytes.NewBuffer(nil)
	err = t.Execute(out, trow)
	if err != nil {
		core.LOG.Panic(err)
	}
	return user.EncodeQueryValue(out.String())
}
