package schedule

import (
	"fmt"
	"netease_control_center/interfaces/log"
	"time"
)

type TaskLevel uint8

const (
	TaskLevel_0 TaskLevel = iota

	TaskLevel_1
	TaskLevel_2
	TaskLevel_3
	TaskLevel_4

	TaskLevel_Common
	TaskLevel_MAX
)

const (
	TaskLevel_SystemService        = TaskLevel_0
	TaskLevel_IotWifiParingService = TaskLevel_1
	TaskLevel_BtOnWifiOff          = TaskLevel_1
	TaskLevel_WifiParing           = TaskLevel_1
	TaskLevel_VoiceEventService    = TaskLevel_2
	TaskLevel_RemindService        = TaskLevel_3
	TaskLevel_AlarmService         = TaskLevel_4
	TaskLevel_NoticePlayer         = TaskLevel_Common
	TaskLevel_VoiceStatusService   = TaskLevel_Common
)

const (
	TaskLevel_Min   = TaskLevel_0
	TaskLevel_Super = TaskLevel_Common - 1
)

type TaskStatus uint8

const (
	TaskStatus_Init        TaskStatus = iota
	TaskStatus_Running
	TaskStatus_Interrupted
)

type RegistedTask struct {
	Interrupt func(ByWho string)
	Resume    func()
	Do        func(canExec bool, scmd SCMD, arg ...interface{})

	//return tast if has been finished
	IsActive func() bool

	//task define
	GetName      func() string
	GetTaskLevel func() TaskLevel

	CanBeInterruptByKey           func() bool
	CanBeInterruptBySameLevelTask func() bool

	GetSupportedSCmd  func() []SCMD
	GetScheduleDomain ScheduleDomainGetFunc

	Debug func() string
}

type TaskHd interface {
	GetTaskStatus() TaskStatus
	SetTaskIdle()
	FinishExec()
}

type STask struct {
	Task       RegistedTask
	TaskStatus TaskStatus

	InterruptedTime  time.Time
	InterruptedByWho string
}

func (this *STask) BeInterruptedByKey() bool {
	if this.Task.CanBeInterruptByKey == nil {
		return false
	} else {
		return this.Task.CanBeInterruptByKey()
	}
}

func (this *STask) GetTaskStatus() TaskStatus {
	return this.TaskStatus
}

func (this *STask) SetTaskIdle() {
	this.TaskStatus = TaskStatus_Init
	if curRunningTask == this {
		curRunningTask = nil
	}
}

func (this *STask) SetTaskStatus(status TaskStatus) {
	this.TaskStatus = status
	if status == TaskStatus_Running {
		log.Println(log.DebugLog, this.Task.GetName()+" has been set running!")
	}
}

func (this *STask) Do(canExec bool, scmd SCMD, arg ...interface{}) {
	this.Task.Do(canExec, scmd, arg...)
}

func (this *STask) Interrupt(ByWho string) {
	if this.GetTaskStatus() == TaskStatus_Interrupted {
		return
	}
	log.Println(log.DebugLog, "Task is been interrupted! ", this.Task.GetName(), "By:", ByWho)

	if this.Task.IsActive() {
		this.Task.Interrupt(ByWho)
	}
	this.SetTaskStatus(TaskStatus_Interrupted)

	this.InterruptedTime = time.Now().Local()
	this.InterruptedByWho = ByWho

	if getRunningTask() != nil && getRunningTask() == this {
		setRunningTask(nil)
	}
}

func (this *STask) Resume() {
	defer func() {
		this.InterruptedByWho = ""
	}()

	if this.Task.Resume != nil {
		this.Task.Resume()
	}
}

func (this *STask) FinishExec() {
	if this.GetTaskStatus() == TaskStatus_Running {
		SendSCmd(SCMD_SChedule, nil)
	}
}

func (this *STask) String() string {
	var ret string
	ret += "\r\n Mod name:" + this.Task.GetName() + "\n"
	ret += " Task status: "
	switch this.TaskStatus {
	case TaskStatus_Init:
		ret += "idle "
	case TaskStatus_Running:
		ret += "running "
	case TaskStatus_Interrupted:
		ret += "interrupted "
	default:
		ret += "unknow "
	}
	ret += "\n"

	ret += " Active:" + fmt.Sprintln(this.Task.IsActive())
	ret += " TaskLevel:" + fmt.Sprintln(this.Task.GetTaskLevel())
	ret += " IsCommonTask:" + fmt.Sprintln(this.Task.GetTaskLevel() == TaskLevel_Common)
	ret += " InterruptTime:" + fmt.Sprintln(this.InterruptedTime)
	ret += " InterruptBy:" + this.InterruptedByWho
	ret += " SupportCmd:" + fmt.Sprintln(this.Task.GetSupportedSCmd())
	if this.Task.CanBeInterruptByKey != nil {
		ret += " CanBeInterruptByKey:" + fmt.Sprintln(this.Task.CanBeInterruptByKey())
	}

	if this.Task.Debug != nil {
		ret += " Debug:" + this.Task.Debug() + "\n"
	}

	return ret
}
