package sensor

import (
	"strconv"
	"strings"

	"github.com/astaxie/beego/orm"

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

const (
	NOTIFICATION_DELIMITER = ","
)

type SensorTable struct {
	Id            int64
	SensorMAC     string
	Description   string
	Interval      int64
	Notifications string
}

func init() {
	orm.RegisterModel(new(SensorTable))
}

func GetSensorByMac(sensorMac string) *SensorTable {
	o := orm.NewOrm()
	o.Using(database.Alias)

	sensor := new(SensorTable)
	ret := new(SensorTable)
	var maps []orm.Params
	_, err := o.QueryTable(sensor).Filter("SensorMAC", sensorMac).Values(&maps)
	if err == nil {
		for _, m := range maps {
			ret.Id = utils.GetInt(m, "Id")
			ret.SensorMAC = utils.GetString(m, "SensorMAC")
			ret.Description = utils.GetString(m, "Description")
			ret.Interval = utils.GetInt(m, "Interval")
			ret.Notifications = utils.GetString(m, "Notifications")
			break
		}
	}

	return ret
}

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

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

func GetAllSensor() []SensorTable {
	o := orm.NewOrm()
	o.Using(database.Alias)

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

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

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

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

func GetSensorByNotificationId(notifId int64) *SensorTable {
	var ret *SensorTable = nil
	allSensors := GetAllSensor()
	for _, s := range allSensors {
		if s.IsContainNotificationId(notifId) {
			ret = &s
			break
		}
	}
	return ret
}

func UpdateSensor(mac, description string, interval int64) {
	o := orm.NewOrm()
	o.Using(database.Alias)

	s := GetSensorByMac(mac)
	if o.Read(s) == nil {
		s.Description = description
		s.Interval = interval
		o.Update(s)
	}
}

func (ss *SensorTable) update() {
	o := orm.NewOrm()
	o.Using(database.Alias)

	mac := ss.SensorMAC
	s := GetSensorByMac(mac)
	if o.Read(s) == nil {
		s.Description = ss.Description
		s.Interval = ss.Interval
		s.Notifications = ss.Notifications
		o.Update(s)
	}
}

func UpdateSensorWithNotifications(mac, description string, interval int64, notifications string) {
	o := orm.NewOrm()
	o.Using(database.Alias)

	s := GetSensorByMac(mac)
	if o.Read(s) == nil {
		s.Description = description
		s.Interval = interval
		s.Notifications = notifications
		o.Update(s)
	}
}

func AddSensor(sensorMac string) {
	o := orm.NewOrm()
	o.Using(database.Alias)
	_, _ = o.Insert(&SensorTable{SensorMAC: sensorMac})
}

func DeleteSensorByMac(sensorMac string) {
	o := orm.NewOrm()
	o.Using(database.Alias)
	o.Delete(&SensorTable{SensorMAC: sensorMac})
}

func DeleteSensor(sensorId int64) {
	o := orm.NewOrm()
	o.Using(database.Alias)
	o.Delete(&SensorTable{Id: sensorId})
}

func (s *SensorTable) GetName() string {
	ret := s.Description
	if s.Description == "" {
		ret = s.SensorMAC
	}
	return ret
}

func (s *SensorTable) GetNotificationsIds() []int64 {
	var ret []int64
	for _, idStr := range strings.Split(s.Notifications, NOTIFICATION_DELIMITER) {
		id, err := strconv.Atoi(idStr)
		if err == nil {
			ret = append(ret, int64(id))
		}
	}
	return ret
}

func (s *SensorTable) IsContainNotificationId(idNotif int64) bool {
	for _, b := range strings.Split(s.Notifications, NOTIFICATION_DELIMITER) {
		bb, err := strconv.Atoi(b)
		if err == nil && int64(bb) == idNotif {
			return true
		}
	}
	return false
}

func (s *SensorTable) AddNotification(notifId int64) {
	if s.Notifications != "" {
		s.Notifications += NOTIFICATION_DELIMITER
	}
	s.Notifications += strconv.FormatInt(notifId, 10)
	s.update()
}

func (s *SensorTable) DeleteNotification(notifId int64) {
	newNotificationStr := ""
	for _, idStr := range strings.Split(s.Notifications, NOTIFICATION_DELIMITER) {
		id, err := strconv.Atoi(idStr)
		if err == nil {
			if int64(id) != notifId {
				if newNotificationStr != "" {
					newNotificationStr += NOTIFICATION_DELIMITER
				}
				newNotificationStr += idStr
			}
		}
	}

	s.Notifications = newNotificationStr
	s.update()
}
