package common

import (
	"database/sql"
	"dbweb/core"
	"dbweb/modules/common/recordview"
	"encoding/json"
	"fmt"

	"github.com/linlexing/dbx/ddb"

	"github.com/linlexing/dbx/data"
	"github.com/linlexing/dbx/pageselect"
)

type eleview struct {
	EleName   string         `db:"ELENAME"`
	Pub       int            `db:"PUB"`
	Owner     string         `db:"OWNER"`
	Name      string         `db:"NAME"`
	Conts     sql.NullString `db:"CONTS"`
	PlainText sql.NullString `db:"PLAINTEXT"`
	DspCols   sql.NullString `db:"DSPCOLS"`
}
type EleView struct {
	EleName   string
	Public    int
	Owner     string
	Name      string
	Conts     []*pageselect.ConditionLine
	PlainText string
	DspCols   []*recordview.DisplayColumn
}
type EleViewItem struct {
	Owner        string `db:"OWNER"`
	Name         string `db:"NAME"`
	DisplayLabel string
}

func LoadEleView(db ddb.DB, eleName string, pub int, owner, name string) *EleView {
	var Conts sql.NullString
	var PlainText sql.NullString
	var DspCols sql.NullString

	if err := db.QueryRow(
		"select conts,plaintext,dspcols from eleview where elename=? and pub=? and owner=? and name=?",
		eleName, pub, owner, name).Scan(&Conts, &PlainText, &DspCols); err != nil {
		core.LOG.Panic(err)
	}

	result := &EleView{
		EleName:   eleName,
		Public:    pub,
		Owner:     owner,
		Name:      name,
		Conts:     []*pageselect.ConditionLine{},
		PlainText: PlainText.String,
		DspCols:   []*recordview.DisplayColumn{},
	}
	if Conts.Valid && len(Conts.String) > 0 {
		if err := json.Unmarshal([]byte(Conts.String), &result.Conts); err != nil {
			core.LOG.Panic(err)
		}
	}
	if DspCols.Valid && len(DspCols.String) > 0 {
		if err := json.Unmarshal([]byte(DspCols.String), &result.DspCols); err != nil {
			core.LOG.Panic(err)
		}
	}
	return result
}
func decodeEleView(ele *eleview) *EleView {
	result := &EleView{
		EleName:   ele.EleName,
		Public:    ele.Pub,
		Owner:     ele.Owner,
		Name:      ele.Name,
		Conts:     []*pageselect.ConditionLine{},
		PlainText: ele.PlainText.String,
		DspCols:   []*recordview.DisplayColumn{},
	}
	if ele.Conts.Valid && len(ele.Conts.String) > 0 {
		if err := json.Unmarshal([]byte(ele.Conts.String), &result.Conts); err != nil {
			core.LOG.Panic(err)
		}
	}
	if ele.DspCols.Valid && len(ele.DspCols.String) > 0 {
		if err := json.Unmarshal([]byte(ele.DspCols.String), &result.DspCols); err != nil {
			core.LOG.Panic(err)
		}
	}
	return result
}
func GetPubEleViewList(db ddb.DB, eleName string, u *core.User) (rev []*EleViewItem, err error) {
	var vout *EleViewItem
	rev = []*EleViewItem{}
	codes := []string{}
	for i := 0; i < len(u.Dept.Code); i++ {
		codes = append(codes, u.Dept.Code[:i+1])
	}
	strSql, pam, err := data.In(
		"select owner,name from eleview where elename=? and pub=1 and owner in (?)",
		eleName, codes)
	if err != nil {
		return
	}
	rows, err := db.Query(strSql, pam...)
	if err != nil {
		return
	}
	defer rows.Close()
	for rows.Next() {
		vout = new(EleViewItem)
		if err = rows.Scan(&vout.Owner, &vout.Name); err != nil {
			return
		}
		vout.DisplayLabel = vout.Owner + "." + vout.Name
		rev = append(rev, vout)
	}
	return
}
func GetPriEleViewList(db ddb.DB, eleName string, u *core.User) (rev []*EleViewItem, err error) {
	rev = []*EleViewItem{}
	rows, err := db.Query("select name from eleview where elename=? and pub=0 and owner = ?",
		eleName, u.Name)
	if err != nil {
		return
	}
	defer rows.Close()
	for rows.Next() {
		var vout EleViewItem
		if err = rows.Scan(&vout.Name); err != nil {
			return
		}
		vout.DisplayLabel = vout.Name
		vout.Owner = u.Name
		rev = append(rev, &vout)
	}
	return
}

func (e *EleView) DisplayLabel() string {
	if e.Public > 0 {
		return e.Owner + "." + e.Name
	}
	return e.Name
}
func InsertEleView(db ddb.DB, data *EleView) error {
	var Conts sql.NullString
	var PlainText sql.NullString
	var DspCols sql.NullString

	if len(data.Conts) > 0 {
		if bys, err := json.Marshal(data.Conts); err != nil {
			core.LOG.Panic(err)
		} else {
			Conts.String = string(bys)
			Conts.Valid = true
		}
	}
	if len(data.DspCols) > 0 {
		if bys, err := json.Marshal(data.DspCols); err != nil {
			core.LOG.Panic(err)
		} else {
			DspCols.String = string(bys)
			DspCols.Valid = true
		}
	}
	if len(data.PlainText) > 0 {
		PlainText.String = data.PlainText
		PlainText.Valid = true
	}
	strSql := "insert into eleview(elename,pub,owner,name,conts,plaintext,dspcols)values(" +
		"?,?,?,?,?,?,?)"

	if sr, err := db.Exec(strSql, data.EleName, data.Public, data.Owner,
		data.Name, Conts, PlainText, DspCols); err != nil {
		return err
	} else {
		if i, err := sr.RowsAffected(); err != nil {
			return err
		} else if i != 1 {
			return fmt.Errorf("the insert fail")
		}
	}
	return nil
}
func UpdateEleView(db ddb.DB, oldName string, data *EleView) error {
	var Conts sql.NullString
	var PlainText sql.NullString
	var DspCols sql.NullString

	if len(data.Conts) > 0 {
		if bys, err := json.Marshal(data.Conts); err != nil {
			core.LOG.Panic(err)
		} else {
			Conts.String = string(bys)
			Conts.Valid = true
		}
	}
	if len(data.DspCols) > 0 {
		if bys, err := json.Marshal(data.DspCols); err != nil {
			core.LOG.Panic(err)
		} else {
			DspCols.String = string(bys)
			DspCols.Valid = true
		}
	}
	if len(data.PlainText) > 0 {
		PlainText.String = data.PlainText
		PlainText.Valid = true
	}
	strSql :=
		`update eleview set 
		name=?,
		conts=?,
		plaintext=?,
		dspcols=? 
	where elename=? and pub=? and owner=? and name=?`

	if sr, err := db.Exec(strSql, data.Name, Conts, PlainText,
		DspCols, data.EleName, data.Public, data.Owner, oldName); err != nil {
		return err
	} else {
		if i, err := sr.RowsAffected(); err != nil {
			return err
		} else if i != 1 {
			return fmt.Errorf("the update fail,RowsAffected:%d", i)
		}
	}
	return nil
}
func DeleteEleView(db ddb.DB, elename string, public int, owner, name string) error {
	if sr, err := db.Exec("delete from eleview where elename=? and pub=? and owner=? and name=?",
		elename, public, owner, name); err != nil {
		return err
	} else {
		if i, err := sr.RowsAffected(); err != nil {
			return err
		} else if i != 1 {
			return fmt.Errorf("the delete fail")
		}
	}
	return nil
}

//ChangeUserEleView 修改一个用户的数据
func ChangeUserEleView(db ddb.DB, oldName, newName string) error {
	_, err := db.Exec("update eleview set owner=? where pub=0 and owner=?", newName, oldName)
	return err
}

//RemoveUserEleView 移除一个用户的数据
func RemoveUserEleView(db ddb.DB, userName string) error {
	_, err := db.Exec("delete from eleview where pub=0 and owner=?", userName)
	return err

}

//ChangeElementEleView 修改一个工作元素的名称
func ChangeElementEleView(db ddb.DB, oldName, newName string) error {
	_, err := db.Exec("update eleview set elename=? where elename=?", newName, oldName)
	return err
}

//RemoveUserEleView 移除一个工作元素相关的数据
func RemoveElementEleView(db ddb.DB, name string) error {
	_, err := db.Exec("delete from eleview where elename=?", name)
	return err

}
