package main

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

	"k8s.io/apimachinery/pkg/util/yaml"

	"bytes"
	// "k8s.io/apimachinery/pkg/runtime"
	"io/ioutil"

)

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"`
	PROCATEGORY			int  `json:"pro_category"`
	SYNDATA				bool `json:"syn_data"`
	SYNEXTENSIONTIME bool `json:"syn_extension_Time"`
	RECORD_LOG_PATH string `json:"record_log_path"`
	MQTT_OPEN bool `json:"mqtt_open"`
	MQTT_BROKER string `json:"mqtt_broker"`
	MQTT_USERNAME string `json:"mqtt_username"`
	MQTT_PASSWORD string `json:"mqtt_password"`
}

//无线 下位机
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"`
	UPDATE_TIME				time.Time `json:"update_time"`
	LORA_GWS			[]string `json:"lora_gws"`
}

var conf Conf
var DEVICEDATAS Devicedatas
var demoDevice Device

var today string

var nodeUpdateMap sync.Map

//sensor data update map
var sensorUpdateMap sync.Map

//key:loragateway ip value:conn object
var loragwMap sync.Map

//key:字符串addr  value:byte[] addr
var sensorMap sync.Map

//log channel
var logch = make(chan []byte)

var loraNodeMap sync.Map

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


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

	//以时间配置随机数种子
	rand.Seed(time.Now().UnixNano())

	t := time.Now()
 	today = t.Format("2006-01-02")

	// configfile, err := os.Open("conf/gateway.conf")
	// check(err)
	// defer configfile.Close()

	// err = json.NewDecoder(configfile).Decode(&conf)
	// check(err)

	configfile, err := os.Open("conf/gateway.yaml")
	check(err)
	defer configfile.Close()
	configData,err := ioutil.ReadAll(configfile)
	check(err)

	reader := bytes.NewReader(configData)
	// ext := runtime.RawExtension{}
	d := yaml.NewYAMLOrJSONDecoder(reader, 4096)
	if err := d.Decode(&conf); err != nil {
		check(err)
	}

	var device Device

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

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

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

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

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

	DEVICEDATAS.Unlock()

	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
}