package teleinfo

import (
	"github.com/astaxie/beego/logs"
	"github.com/astaxie/beego/orm"

	"git.kingpenguin.tk/chteufleur/datahouse.git/models/database"
	"git.kingpenguin.tk/chteufleur/datahouse.git/models/utils"
	"git.kingpenguin.tk/chteufleur/datahouse.git/models/variables"

	"time"
)

const (
	AdresseCompteur      = "ADCO"
	OptionTarifaire      = "OPTARIF"
	OptionBase           = "BASE"   // Wh
	IntensiteSouscrite   = "ISOUSC" // A
	IntensiteInstantanne = "IINST"  // A
	IntensiteMax         = "IMAX"   // A
	PuissanceApparente   = "PAPP"   // VA
)

var (
	_, timezoneOffset = time.Now().Zone()
	log               = logs.NewLogger(10000)

	optionTarifaireTranslate = make(map[string]string)
)

func init() {
	log.SetLogger(variables.LogType, variables.LogParams)
	orm.RegisterModel(new(TeleinfoTable), new(CompteurTeleinfoTable))
	orm.DefaultRowsLimit = database.RowLimit

	optionTarifaireTranslate["BASE"] = "Base"
	optionTarifaireTranslate["HC.."] = "Heures Creuses"
	optionTarifaireTranslate["EJP."] = "EJP"
}

//——————————————————————————————————————————————————————————————————————————————
//                           TeleinfoTable
//——————————————————————————————————————————————————————————————————————————————
type TeleinfoTable struct {
	Id                   int64
	HorodateGMT          time.Time `orm:"auto_now;type(datetime)"`
	AdresseCompteur      string
	OptionTarifaire      string
	OptionBase           int64
	IntensiteSouscrite   int64
	IntensiteInstantanne int64
	IntensiteMax         int64
	PuissanceApparente   int64
}

func AddData(adresse, tarif string, base, isousc, iinst, imax, papp int64) {
	log.Info("Add teleinfo {adresse: %s, tarif: %s, base: %s Wh, isousc: %d A, iinst: %d A, imax: %d A, ppap: %d VA}", adresse, tarif, base, isousc, iinst, imax, papp)
	o := orm.NewOrm()
	o.Using(database.Alias)

	ti := new(TeleinfoTable)
	ti.AdresseCompteur = adresse
	ti.OptionTarifaire = tarif
	ti.OptionBase = base
	ti.IntensiteSouscrite = isousc
	ti.IntensiteInstantanne = iinst
	ti.IntensiteMax = imax
	ti.PuissanceApparente = papp
	o.Insert(ti)
}

func GetAllDataForCompteur(adresseCompteur string) []TeleinfoTable {
	o := orm.NewOrm()
	o.Using(database.Alias)

	var dataArray []TeleinfoTable
	var maps []orm.Params
	_, err := o.QueryTable(new(TeleinfoTable)).Filter("AdresseCompteur", adresseCompteur).Values(&maps)
	if err == nil {
		for _, m := range maps {
			d := new(TeleinfoTable)
			d.Id = utils.GetInt(m, "Id")
			d.HorodateGMT = utils.GetTime(m, "HorodateGMT")

			d.AdresseCompteur = utils.GetString(m, "AdresseCompteur")
			d.OptionTarifaire = optionTarifaireTranslate[utils.GetString(m, "OptionTarifaire")]
			d.OptionBase = utils.GetInt(m, "OptionBase")

			d.IntensiteSouscrite = utils.GetInt(m, "IntensiteSouscrite")
			d.IntensiteInstantanne = utils.GetInt(m, "IntensiteInstantanne")
			d.IntensiteMax = utils.GetInt(m, "IntensiteMax")

			d.PuissanceApparente = utils.GetInt(m, "PuissanceApparente")

			dataArray = append(dataArray, *d)
		}
	}
	return dataArray
}

func GetLastDataForCompteur(adresseCompteur string) *TeleinfoTable {
	o := orm.NewOrm()
	o.Using(database.Alias)

	data := new(TeleinfoTable)
	var maps []orm.Params
	_, err := o.QueryTable(new(TeleinfoTable)).Filter("AdresseCompteur", adresseCompteur).OrderBy("HorodateGMT").Values(&maps)
	if err == nil {
		for _, m := range maps {
			data.Id = utils.GetInt(m, "Id")
			data.HorodateGMT = utils.GetTime(m, "HorodateGMT")

			data.AdresseCompteur = utils.GetString(m, "AdresseCompteur")
			data.OptionTarifaire = optionTarifaireTranslate[utils.GetString(m, "OptionTarifaire")]
			data.OptionBase = utils.GetInt(m, "OptionBase")

			data.IntensiteSouscrite = utils.GetInt(m, "IntensiteSouscrite")
			data.IntensiteInstantanne = utils.GetInt(m, "IntensiteInstantanne")
			data.IntensiteMax = utils.GetInt(m, "IntensiteMax")

			data.PuissanceApparente = utils.GetInt(m, "PuissanceApparente")
		}
	}
	return data
}

func GetNextData(addressCompteur string, from time.Time) []TeleinfoTable {
	o := orm.NewOrm()
	o.Using(database.Alias)

	var dataArray []TeleinfoTable
	var maps []orm.Params
	_, err := o.QueryTable(new(TeleinfoTable)).Filter("AdresseCompteur", addressCompteur).Filter("HorodateGMT__gt", from).OrderBy("HorodateGMT").Values(&maps)
	if err == nil {
		for _, m := range maps {
			dataTime := utils.GetTime(m, "HorodateGMT")
			if dataTime.After(from) {
				d := new(TeleinfoTable)
				d.Id = utils.GetInt(m, "Id")
				d.HorodateGMT = dataTime

				d.AdresseCompteur = utils.GetString(m, "AdresseCompteur")
				d.OptionTarifaire = optionTarifaireTranslate[utils.GetString(m, "OptionTarifaire")]
				d.OptionBase = utils.GetInt(m, "OptionBase")

				d.IntensiteSouscrite = utils.GetInt(m, "IntensiteSouscrite")
				d.IntensiteInstantanne = utils.GetInt(m, "IntensiteInstantanne")
				d.IntensiteMax = utils.GetInt(m, "IntensiteMax")

				d.PuissanceApparente = utils.GetInt(m, "PuissanceApparente")

				dataArray = append(dataArray, *d)
			}
		}
	}
	return dataArray
}

func DeleteDataCompteur(adresseCompteur string) {
	o := orm.NewOrm()
	o.Using(database.Alias)
	o.Delete(&TeleinfoTable{AdresseCompteur: adresseCompteur})
}

//——————————————————————————————————————————————————————————————————————————————
//                           CompteurTeleinfoTable
//——————————————————————————————————————————————————————————————————————————————
type CompteurTeleinfoTable struct {
	Id              int64
	AdresseCompteur string
	Description     string
}

func GetCompteurByAdresse(adresse string) *CompteurTeleinfoTable {
	o := orm.NewOrm()
	o.Using(database.Alias)

	ret := new(CompteurTeleinfoTable)
	var maps []orm.Params
	_, err := o.QueryTable(new(CompteurTeleinfoTable)).Filter("AdresseCompteur", adresse).Values(&maps)
	if err == nil {
		for _, m := range maps {
			ret.Id = utils.GetInt(m, "Id")
			ret.AdresseCompteur = utils.GetString(m, "AdresseCompteur")
			ret.Description = utils.GetString(m, "Description")
			break
		}
	}

	return ret
}

func GetAllCompteurIds() []int64 {
	o := orm.NewOrm()
	o.Using(database.Alias)

	var ret []int64
	var maps []orm.Params
	_, err := o.QueryTable(new(CompteurTeleinfoTable)).Values(&maps)
	if err == nil {
		for _, m := range maps {
			ret = append(ret, utils.GetInt(m, "Id"))
		}
	}
	return ret
}

func GetAllCompteur() []CompteurTeleinfoTable {
	o := orm.NewOrm()
	o.Using(database.Alias)

	var ret []CompteurTeleinfoTable
	var maps []orm.Params
	_, err := o.QueryTable(new(CompteurTeleinfoTable)).Values(&maps)
	if err == nil {
		for _, m := range maps {
			r := new(CompteurTeleinfoTable)
			r.Id = utils.GetInt(m, "Id")
			r.AdresseCompteur = utils.GetString(m, "AdresseCompteur")
			r.Description = utils.GetString(m, "Description")

			ret = append(ret, *r)
		}
	}
	return ret
}

func GetSensor(id int64) *CompteurTeleinfoTable {
	o := orm.NewOrm()
	o.Using(database.Alias)

	var ret = new(CompteurTeleinfoTable)
	var maps []orm.Params
	_, err := o.QueryTable(new(CompteurTeleinfoTable)).Filter("Id", id).Values(&maps)
	if err == nil {
		for _, m := range maps {
			ret.Id = utils.GetInt(m, "Id")
			ret.AdresseCompteur = utils.GetString(m, "AdresseCompteur")
			ret.Description = utils.GetString(m, "Description")
		}
	}
	return ret
}

func UpdateCompteur(adresse, description string) {
	o := orm.NewOrm()
	o.Using(database.Alias)

	s := GetCompteurByAdresse(adresse)
	if o.Read(s) == nil {
		s.AdresseCompteur = adresse
		s.Description = description
		o.Update(s)
	}
}

func AddCompteur(adresse string) {
	o := orm.NewOrm()
	o.Using(database.Alias)
	_, _ = o.Insert(&CompteurTeleinfoTable{AdresseCompteur: adresse})
}

func DeleteCompteurByAdresse(adresse string) {
	o := orm.NewOrm()
	o.Using(database.Alias)
	o.Delete(&CompteurTeleinfoTable{AdresseCompteur: adresse})

	DeleteDataCompteur(adresse)
}

func DeleteCompteur(compteurId int64) {
	compteur := GetSensor(compteurId)
	o := orm.NewOrm()
	o.Using(database.Alias)
	o.Delete(&CompteurTeleinfoTable{Id: compteurId})

	DeleteDataCompteur(compteur.AdresseCompteur)
}
