package controller

import (
	"encoding/json"
	"netease_control_center/globals"
	"netease_control_center/interfaces/log"
	"netease_control_center/modules/hardware/led_mcu"
	"netease_control_center/modules/hardware/mcu_leds/atservice"
	"sync"
	"time"
)

var (
	cronMicLock sync.Mutex
)

type CronMic struct {
	StartTimeStamp  int64 `json:"startT"`
	EndTimeStamp    int64 `json:"endT"`
	UpdateTimeStamp int64 `json:"updateT"`
	MainSwitch      bool  `json:"mainSwitch"`
	LightSwitch     bool  `json:"lightSwitch"`
}

var (
	ChinaLocation, _ = time.LoadLocation("Asia/Shanghai")
	micControl       = CronMic{MainSwitch: true, LightSwitch: true, StartTimeStamp: time.Date(2018, 1, 1, 0, 0, 0, 0, ChinaLocation).Unix() * 1000,
		EndTimeStamp: time.Date(2018, 1, 1, 7, 0, 0, 0, ChinaLocation).Unix() * 1000}
)

func init() {
	globals.MicCron.RegisterCb(func(e interface{}, cbType globals.CallCbType) {
		if status, ok := e.(string); ok {
			cronMicLock.Lock()
			defer cronMicLock.Unlock()

			var tmp CronMic
			log.Println(log.DebugLog, "Get mic status:", status)
			if err := json.Unmarshal([]byte(status), &tmp); err == nil {
				log.Printf(log.DebugLog, "New mic status:%+v, old:%+v, eq:%+v, type=%+v\n", tmp, micControl, tmp == micControl, cbType)
				if cbType == globals.CHANGE_CALL && tmp != micControl {
					micControl = tmp
					UpdateMicStatus(false)
					CrontabInit()
					UpdateCronTime()
				}

				if tmp != micControl {
					log.Println(log.DebugLog, "Update cur miccontrol!")
					micControl = tmp
				}
			} else {
				log.Println(log.ErrorLog, "json err:", err)
			}
		} else {
			log.Println(log.ErrorLog, "mic cron type error!")
		}
	})
}

func UpdateMicStatus(lock bool) {
	if lock {
		cronMicLock.Lock()
		defer cronMicLock.Unlock()
	}

	now := time.Now()

	_start := time.Unix(micControl.StartTimeStamp/1000, 0).In(ChinaLocation)
	_end := time.Unix(micControl.EndTimeStamp/1000, 0).In(ChinaLocation)

	start := time.Date(now.Year(), now.Month(), now.Day(), _start.Hour(), _start.Minute(), 0, 0, now.Location())
	end := time.Date(now.Year(), now.Month(), now.Day(), _end.Hour(), _end.Minute(), 0, 0, now.Location())

	if start.After(end) {
		//here means jump over day
		if now.Before(end) {
			start = start.AddDate(0, 0, -1)
		} else {
			end = end.AddDate(0, 0, 1)
		}
	}
	log.Printf(log.DebugLog, "Begin to update mic status:%+v, start:%+v, end: %+v\n", micControl, start, end)
	log.Println(log.DebugLog, (start.Hour() == end.Hour() && start.Minute() == end.Minute()), (now.After(start) && now.Before(end)))

	if micControl.MainSwitch == true && ((start.Hour() == end.Hour() && start.Minute() == end.Minute()) || (now.After(start) && now.Before(end))) {
		log.Println(log.DebugLog, "In auto mic close durtion!")
		if globals.IsMicClose == false {
			log.Println(log.DebugLog, "Mic close = false")
			globals.IsMicClose = true
			globals.MicCloseTrig = globals.WhoCLoseMic_Auto
		}

		if micControl.LightSwitch == true {
			log.Println(log.DebugLog, "Mic light is enable!", globals.IsMicLightOn)
			MicLightSwitch(true, false)
		} else {
			log.Println(log.DebugLog, "Mic light is not enable!", globals.IsMicLightOn)
			MicLightSwitch(false, false)
		}
	} else {
		log.Println(log.DebugLog, "Not in auto mic close durtion", globals.MicCloseTrig)
		if globals.MicCloseTrig == globals.WhoCLoseMic_Auto {
			globals.IsMicClose = false
		} else {
			log.Println(log.DebugLog, "User control mic, do nothing!")
		}

		SetMicClose(globals.IsMicClose, globals.WhoCLoseMic_User, false)
	}
}

func SetMicClose(isMicClose bool, who globals.WhoCLoseMic, lock bool) {
	if lock {
		cronMicLock.Lock()
		defer cronMicLock.Unlock()
	}

	globals.IsMicClose = isMicClose
	MicLightSwitch(isMicClose, false)
	globals.MicCloseTrig = who
}

func MicLightSwitch(on bool, lock bool) {
	if lock {
		cronMicLock.Lock()
		defer cronMicLock.Unlock()
	}

	switch {
	case on == true && globals.IsMicLightOn == false:
		led_mcu.DirectLedControl(atservice.GUIDE_EFFECT_ID_MIC_OFF, atservice.GUIDE_ACTION_START, 6, []byte{})
		globals.IsMicLightOn = true

	case on == false && globals.IsMicLightOn == true:
		led_mcu.DirectLedControl(atservice.GUIDE_EFFECT_ID_MIC_OFF, atservice.GUIDE_ACTION_STOP, 6, []byte{})
		globals.IsMicLightOn = false

	}
}

func micCronStart() {
	log.Printf(log.DebugLog, "Mic cron start!%+v, %+v\n", micControl, globals.IsMicClose)
	if micControl.MainSwitch == true {
		cronMicLock.Lock()
		defer cronMicLock.Unlock()

		if globals.IsMicClose == false {
			log.Println(log.DebugLog, "Mic close = false")
			globals.IsMicClose = true
			globals.MicCloseTrig = globals.WhoCLoseMic_Auto
		}

		if micControl.LightSwitch == true {
			MicLightSwitch(true, false)
		} else {
			MicLightSwitch(false, false)
		}
	}
}

func micCronEnd() {
	log.Printf(log.DebugLog, "Mic cron end!%+v, %+v\n", micControl, globals.IsMicClose)
	if micControl.MainSwitch == true {
		cronMicLock.Lock()
		defer cronMicLock.Unlock()

		if globals.MicCloseTrig == globals.WhoCLoseMic_Auto && globals.IsMicClose == true {
			globals.IsMicClose = false
		}

		SetMicClose(globals.IsMicClose, globals.WhoCLoseMic_User, false)
	}
}
