package schedule

import (
	"fmt"
	"netease_control_center/globals"
	"netease_control_center/interfaces/eventPoint"
	"netease_control_center/interfaces/http"
	"netease_control_center/interfaces/log"
	"time"
)

var (
	scenePlayerHd PlayerHd
)

const (
	waitDuritionWhenInterrupt = 1 * time.Minute
)

func scenePlayer_stop() {
	LockScene()
	defer UnlockScene()
	if curscene == nil {
		log.Println(log.DebugLog, "scene is nil !!!")
		return
	}
	curscene.Exit()
}

func scenePlayer_pause() {
	LockScene()
	defer UnlockScene()
	if curscene == nil {
		log.Println(log.DebugLog, "scene is nil !!!")
		return
	}

	if curscene.TaskStatus == SceneTaskStatus_Playing {
		curscene.Pause(true)
	}
	curscene.PlayAfterResume = false
}

func scenePlayer_PlayNext(arg interface{}) {
	LockScene()
	defer UnlockScene()
	if curscene != nil {
		if st, err := curscene.GetCurLocalSceneTask(); err == nil && st.PlayNext != nil {
			st.PlayNext(curscene)
		} else {
			log.Println(log.DebugLog, "Play next but cur tast maybe not support!")
		}
	}
}

func scenePlayer_PlayPre(arg interface{}) {
	LockScene()
	defer UnlockScene()
	if curscene != nil {
		if st, err := curscene.GetCurLocalSceneTask(); err == nil && st.PlayPre != nil {
			st.PlayPre(curscene)
		} else {
			log.Println(log.DebugLog, "Play pre but cur tast maybe not support!")
		}
	}
}

func scenePlayer_seek(pos uint32) {
	LockScene()
	defer UnlockScene()
	if curscene != nil {
		if st, err := curscene.GetCurLocalSceneTask(); err == nil && st.Seek != nil {
			st.Seek(curscene, pos)
		} else {
			log.Println(log.DebugLog, "Play Seek but cur tast maybe not support!")
		}
	}
}

func scenePlayer_StatusChange(status PlayerDetail) {
	LockScene()
	defer UnlockScene()
	if curscene != nil {
		if st, err := curscene.GetCurLocalSceneTask(); err == nil && st.PlayerStatusChange != nil {
			st.PlayerStatusChange(status, curscene)
		}
	}
}

func scenePlayer_Play(start int, arg SCmd_Args) bool {
	LockScene()
	defer UnlockScene()

	if curscene == nil {
		log.Println(log.DebugLog, "scene is nil !!!")
		return false
	}

	curscene.Exec(true)

	return true
}

func InterruptScene() {
	LockScene()
	defer UnlockScene()

	if curscene == nil {
		log.Println(log.DebugLog, "scene is nil !!!")
		return
	}

	if curscene.InterruptStatus == true {
		return
	}

	if curscene.TaskStatus == SceneTaskStatus_Playing {
		curscene.Pause(false)
		curscene.PlayAfterResume = true
	}
	curscene.InterruptStatus = true

	if curscene.TimeoutTimer != nil {
		curscene.TimeoutTimer.Stop()
		curscene.TimeoutTimer = nil
	}
}

func ResumeScene() {
	LockScene()
	defer UnlockScene()

	_resumeScene()
}

func _resumeScene() {
	if curscene == nil {
		log.Println(log.DebugLog, "Resume scene but scene is nil && do scene exit!!!")
		SendSCmd(SCMD_Scene_Exit)

		return
	}

	if curscene.InterruptStatus == false {
		//log.Println(log.DebugLog, "Cur scene not interrupt!! do not resume!")
		return
	}
	curscene.InterruptStatus = false

	if curscene.HasRequestedWhenInterrupt == true {
		curscene.HasRequestedWhenInterrupt = false
		if time.Now().Sub(curscene.RequestedTime) > waitDuritionWhenInterrupt {
			log.Println(log.DebugLog, "Wait timeout beyond ", waitDuritionWhenInterrupt, curscene.RequestedTime)
			SceneExit()
		}
	}

	if curscene.SceneNewEnter || curscene.PlayAfterResume == true {
		curscene.Exec(false)
	}
}

func GetCurScenePlayerDetail() PlayerDetail {
	if scenePlayerHd != nil {
		return scenePlayerHd.GetPlayerStatus()
	} else {
		return PlayerDetail{}
	}
}

func EnterScene(canExec bool, scene interface{}) (isSuccess bool) {
	LockScene()
	defer UnlockScene()

	var tmp SScene
	switch scene.(type) {
	case string:
		tmp.SceneId = scene.(string)
		if err := tmp.Init(); err != nil {
			log.Println(log.DebugLog, "Can not enter scene:", scene, " err:", err)
			return false
		}
	case http.Scene:
		tmp.Scene = scene.(http.Scene)
		tmp.SceneId = tmp.Scene.Id
		tmp.SetTaskStatus(SceneTaskStatus_Init)
	}

	if curscene != nil {
		if curscene.TaskStatus == SceneTaskStatus_Playing {
			curscene.Pause(false)
		}
	}

	tmp.LastScene = curscene
	curscene = &tmp
	curscene.InitSceneEnter()
	curscene.SceneEnterTime = time.Now()

	eventPoint.EpRecord("F411", map[string]interface{}{"scene": curscene.SceneId})
	if canExec {
		curscene.Exec(true)
	} else {
		curscene.HasRequestedWhenInterrupt = true
		curscene.RequestedTime = time.Now()
	}

	return true
}

func scenePlayer_playOrpause() (isPause bool) {
	LockScene()
	defer UnlockScene()

	if curscene == nil {
		log.Println(log.DebugLog, "scene is nil !!!")
		return false
	}

	if curscene.InterruptStatus == true {
		//do nothing
		log.Println(log.DebugLog, "Cur scene interrupted, do nothing! for play or pause!")
		_resumeScene()
		return false
	} else {
		if curscene.TaskStatus == SceneTaskStatus_Playing {
			curscene.IgnoreVolRestore = true

			curscene.Pause(true)
			curscene.PlayAfterResume = false
			eventPoint.PlayPauseEvent(eventPoint.ModelValPause, curRunningPlayer.GetPlayerStatus().Uuid)
			return true
		} else {
			curscene.Exec(true)
			eventPoint.PlayPauseEvent(eventPoint.ModelValPlay, curRunningPlayer.GetPlayerStatus().Uuid)
			return false
		}
	}
}

func init() {
	var player RegistedPlayer
	var err error

	player.IfForcePause = func() bool {
		return false
	}
	player.Stop = scenePlayer_stop
	player.GetPlayerName = func() string {
		return "ScenePlayer"
	}
	player.IsOnline = func() bool {
		return true
	}
	player.GetPlayerCategory = func() PlayerCategory {
		return PlayerCategory_Scene
	}
	player.PrepareNext = func(arg interface{}) {

	}
	player.Pause = scenePlayer_pause
	player.PlayNext = scenePlayer_PlayNext
	player.PlayPre = scenePlayer_PlayPre
	player.PlayerStatusChange = scenePlayer_StatusChange
	player.Play = scenePlayer_Play
	player.Seek = scenePlayer_seek
	player.InterruptPlayer = InterruptScene
	player.ResumePlayer = ResumeScene
	player.EnterScene = EnterScene
	player.PlayOrPause = scenePlayer_playOrpause

	player.Debug = func() string {
		var tmp string
		LockScene()
		defer UnlockScene()
		if curscene != nil {
			tmp += fmt.Sprintf("  Scene:%s(%s)\n", curscene.Scene.Name, curscene.SceneId)
			if st, err := curscene.GetCurServerScenetask(); err == nil {
				tmp += fmt.Sprintf("    Cur scenetask:%+v\n", *st)
			}
			tmp += fmt.Sprintf("    TaskNo:%d\n", curscene.CurTask)
			tmp += fmt.Sprintf("    GetCurTaskNo:0x%x\n", curscene.GetCurTaskNo())

			tmp += fmt.Sprintf("    Time remain:%+v\n", curscene.TimeRemain)
			tmp += fmt.Sprintf("    Real time remain:%+v\n", curscene.GetRemainTime())
			tmp += fmt.Sprintf("    Last Paused time:%+v\n", curscene.LastPausedTime)
			tmp += fmt.Sprintf("    Last Play time:%+v\n", curscene.LastPlayTime)
			tmp += fmt.Sprintf("    Last Time remain:%+v\n", curscene.TimeRemain)
			tmp += fmt.Sprintf("    Scene new enter:%+v\n", curscene.SceneNewEnter)
			tmp += fmt.Sprintf("    Task new enter:%+v\n", curscene.TaskNewEnter)
			tmp += fmt.Sprintf("    Interrupt status:%+v\n", curscene.InterruptStatus)

			tmp += fmt.Sprintf("    HasRequestedWhenInterrupt status:%+v\n", curscene.HasRequestedWhenInterrupt)
			tmp += fmt.Sprintf("    RequestedTime:%+v\n", curscene.RequestedTime)
			tmp += fmt.Sprintf("    PlayAfterResume:%+v\n", curscene.PlayAfterResume)
			tmp += fmt.Sprintf("    Oemargs:%+v\n", curscene.OemArg)
			tmp += fmt.Sprintln("    Enter tts:", curscene.GetEnterTts())
			tmp += fmt.Sprintln("    Exit tts:", curscene.GetExitTts())

			tmp += fmt.Sprintf("    Scene && Tasks:%+v\n", curscene.Scene)
		}
		return tmp
	}

	if err, scenePlayerHd = RegistePlayer(player, globals.PlayerType_Other); err != nil {
		log.Println(log.ErrorLog, "Registe ", player.GetPlayerName(), " result:", err)
	}
}
