package main

import (
	"database/sql"
	"encoding/json"
	_ "github.com/mattn/go-sqlite3"
	"log"
	"os"
	"strconv"
	"time"
	"sync"
)

type Traffic struct {
	TRAFFIC uint16 `json:"traffic"`
}

type Satisfaction struct {
	SATISFACTION float64 `json:"satisfaction"`
}

type Conf struct {
	GATEWAY_INFO     Gateway_info            `json:"gateway_info"`
	DEVICES_LIST     [][]string              `json:"devices_list`
	SERIALPORTS_LIST map[string]Serialconf   `json:"serialports_list"`
	RS485DEVICES     map[string]Rs485devices `json:"rs485devices"`
	ICONURL          string                  `json:"iconurl`
	WEBSOCKETURL     []string                `json:"websocketurl"`
	POST_TO_SERVER   string                  `json:"post_to_server"`
	DEBUG            bool                    `json:"debug"`
	//是否初始化时打开串口
	OPENSERIAL bool `json:"openserial"`
	//无线 设备
	WIRELESSSLAVEDEVICES []WirelessSlaveDevice `json:"wireless_slave_devices"`
	//是否启动tcpserver
	OPENTCPSETVER bool `json:"open_tcp_server"`
	CHECKSERIAL   bool `json:"check_serial"`
	LORANODES						[]LoraNode								`json:"lora_nodes"`
	DPARKLOCATION		string									`json:"dpark_location"`
	TCPPORT				int		`json:"tcp_port"`
	APIPORT				int		`json:"api_port"`
}

//无线 下位机
type WirelessSlaveDevice struct {
	ADRH    int    `json:"adrh"`
	ADRL    int    `json:"adrl"`
	TYPE    int    `json:"type"`
	VERSION string `json:"version"`
	FLIP    bool   `json:"flip"`
	ID      string `json:"id"`
}

type Gateway_info struct {
	ID       string    `json:"id"`
	VERSION  string    `json:"version"`
	LOCATION []float64 `json:"location"`
	UNITNAME string    `json:"单位"`
	CONFIG   []Config  `json:"config"`
}

type Config struct {
	ID      string          `json:"id"`
	VERAION string          `json:"version"`
	DATA    [][]interface{} `json:"data"`
}

type Rs485devices struct {
	VERSION string   `json:"version"`
	NUM     string   `json:"num"`
	COMMAND [][]byte `json:"command"`
}

type Serialconf struct {
	COM         string `json:"com"`
	BAUDS       int    `json:"bauds"`
	SIZE        uint16 `json:"size"`
	PARITY      string `json:"parity"`
	STOPBITS    int    `json:"stopbits"`
	READTIMEOUT int    `json:"readtimeout"`
	NOTE        string `json:"note"`
}

type LoraNode struct{
	ADR					string `json:"adr"`
	LOCATION_TYPE		string `json:"location_type"`
	LOCATION_CODE		string `json:"location_code"`
	LOCATION_DATA		string	`json:"location_data"`
	TIME					time.Time			`json:"time"`
	CURRENT_DATA		int 		`json:"current_data"`
	CHECK_TIME			bool 		`json:"check_time"`
	DEVICE 					string	`json:"device"`
}

var conf Conf
var DEVICEDATAS Devicedatas
var demoDevice Device


var airDevice Device

var femaledemoDevice Device
var maledemoDevice Device


var db, _ = sql.Open("sqlite3", "./db/gateway.db")

var loraNodeMap sync.Map

// 加载配置文件
func init() {

	time.Now()

	configfile, err := os.Open("conf/gateway.conf")
	check(err)
	defer configfile.Close()
	err = json.NewDecoder(configfile).Decode(&conf)
	check(err)
	var device Device

	// log.Println("slaveDevices:", conf.WIRELESSSLAVEDEVICES)

	for _,v := range conf.LORANODES {
			v.CURRENT_DATA = -1
			// log.Println("&&&&&&&&&&&&&&&&&&&",v)
			v.TIME = time.Now()
			loraNodeMap.Store(v.ADR,v)
	}

	DEVICEDATAS.Lock()
	DEVICEDATAS.DATA = make(map[string]Device)

	//校验是否有设置重复串口
	//var serialPort = make(map[string]int)

	//初始化设备,目前conf.DEVICES_LIST
	for _, i := range conf.DEVICES_LIST {

		//if _, c := serialPort[i[1]]; c {
		//	log.Println("repeatd serial port:", i[1])
		//	os.Exit(3)
		//} else {
		//	serialPort[i[1]] = 0
		//}

		device.DATA = make(map[string]interface{})
		device.ID = i[0]
		device.VERSION = i[2]
		//版本号+编号
		DEVICEDATAS.DATA[i[2]+"_"+i[3]] = device
	}

	DEVICEDATAS.Unlock()

	demoDevice.ID = "deb03e28-ddcb-4e5d-aa31-d870a1f0f09b"
	demoDevice.VERSION = "yunhorn_kgl_c8_v1"
	demoDevice.DATA = make(map[string]interface{})
	for a := 0; a < 8; a++ {
		demoDevice.DATA["data"+strconv.Itoa(a+1)] = 0
	}

	demoDevice.ONLINE = true
	log.Println("init demoDevice success:", demoDevice)

	airDevice.DATA = make(map[string]interface{})
	airDevice.DATA["data"] = 0

	var device2 Device
	device2.Lock()
	device2.ID = demoDevice.ID
	device2.VERSION = demoDevice.VERSION
	device2.ONLINE = demoDevice.ONLINE
	device2.DATA = make(map[string]interface{})

	device2.DATA["data7"] = 0
	device2.DATA["data8"] = 0

	device2.Unlock()
	//DEVICEDATAS.DATA[demoDevice.VERSION+"_1"] = device2

	femaledemoDevice.ID = "8E146028-E1B1-4AC9-8F47-01376A22CB35"
	femaledemoDevice.VERSION = "yunhorn_kgl_c8_v1"
	femaledemoDevice.DATA = make(map[string]interface{})
	femaledemoDevice.ONLINE = true
	femaledemoDevice.DATA["data1"] = 0

	//3是男厕
	DEVICEDATAS.DATA[demoDevice.VERSION+"_3"] = femaledemoDevice

	//2是女厕  配置演示使用
	maledemoDevice.ID = "7BB22E6A-ED0D-4161-8370-6B722D3683B7"
	maledemoDevice.VERSION = "yunhorn_kgl_c8_v1"
	maledemoDevice.DATA = make(map[string]interface{})
	maledemoDevice.ONLINE = true
	maledemoDevice.DATA["data1"] = 0
	maledemoDevice.DATA["data2"] = 0
	//3是男厕
	DEVICEDATAS.DATA[demoDevice.VERSION+"_2"] = maledemoDevice


	go dbdata_init()

}

var good, bad float64
var traffic_data Traffic
var satisfaction_data Satisfaction

// 初始化评价数据和人流量数据
func dbdata_init() {
	rows, err := db.Query("SELECT good, bad FROM satisfaction order by id DESC limit 1")
	if err != nil {
		good = 1
		bad = 0

	} else {
		rows.Next()
		rows.Scan(&good, &bad)
		rows.Close()
	}
	//在原本没有db文件的情况下调用 会报错
	// rows.Close()
	rows, err = db.Query("SELECT traffic FROM traffic t where datetime(t.create_time) > datetime('now','start of day','-1 day') order by id DESC limit 1 ")
	if err != nil {
		traffic_data.TRAFFIC = 0
	} else {
		rows.Next()
		rows.Scan(&traffic_data.TRAFFIC)
		rows.Close()
	}
	//在原本没有db文件的情况下调用 会报错
	//  rows.Close()
}

// 定时更新评价数据和人流数据
func savedata_cron() {
	T := time.Now().Format("2006-01-02")
	stmt, err := db.Prepare("UPDATE satisfaction set  good=?, bad=? ,create_time=? where id=(SELECT max(id) FROM satisfaction)")
	check(err)
	stmt.Exec(&good, &bad, &T)
	stmt, err = db.Prepare("UPDATE traffic set traffic=?, create_time=? where id=(SELECT max(id) FROM traffic)")
	check(err)
	stmt.Exec(&traffic_data.TRAFFIC, &T)
}

// 每天0点插入一条数据
//TODO 刚好有人流量数据
func insertdata() {
	T := time.Now().Format("2006-01-02")
	stmt, _ := db.Prepare(`INSERT INTO traffic (traffic, create_time) values (?, ?)`)
	stmt.Exec(&traffic_data.TRAFFIC, &T)
	traffic_data.TRAFFIC = 0
}