package schedule

import (
	"sync"
	"netease_control_center/interfaces/log"
	"time"
	"netease_control_center/globals"
	"netease_control_center/interfaces/vui"
	"netease_control_center/interfaces/eventPoint"
	"netease_control_center/modules/hardware/misc"
)

var (
	corelock         sync.Mutex
	coreChan         = make(chan SCmdStruct, 50)
	curRunningTask   *STask
	curRunningPlayer *SPlayer

	//music and scene
	isMusicMode = true

	//global pause
	isGlobalPause bool = false

	isNewStart bool = true
)

const (
	//key interrupt
	ModuleName_Key = "keyboard"

	ModuleName_VoiceWakeUp = "voiceWakeUpModule"

	ModuleName_SystemService = "system_service"

	ModuleName_UserTrig = "UserModule"
)

func IsUserEvent(moduleName string) bool {
	switch moduleName {
	case ModuleName_Key, ModuleName_VoiceWakeUp, ModuleName_SystemService, ModuleName_UserTrig:
		return true
	default:
		return false
	}
}

func GetCurPlayerPauseReason() PlayerPauseReason {
	if tmp := curRunningPlayer; tmp != nil {
		return tmp.GetPauseReason()
	} else {
		return PlayerPauseReason_Other
	}
}

func GetMusicField() (st globals.MusicFieldSt) {
	defer func() {
		if err := recover(); err != nil {
			st = globals.NULL_FIELD_ST
			log.Println(log.ErrorLog, err)
		}
		globals.CurCurrentStatus = st
	}()

	if curRunningPlayer == nil || isNewStart == true {
		return globals.NULL_FIELD_ST
	}
	switch globals.PlayerType(curRunningPlayer.GetPlayerId()) {
	case globals.PlayerType_Airplay:
		return globals.WIFIMUSIC_FIELD_ST
	case globals.PlayerType_Bt:
		return globals.WIFIMUSIC_FIELD_ST
	case globals.PlayerType_Dlna:
		return globals.WIFIMUSIC_FIELD_ST
	case globals.PlayerType_Wifi:
		return globals.WIFIMUSIC_FIELD_ST
	}

	if scenePlayerHd != nil && scenePlayerHd.GetPlayerId() == curRunningPlayer.GetPlayerId() {
		return globals.SCENE_FIELD_ST
	}

	return globals.NULL_FIELD_ST
}
func GetGlobalPause() bool {
	return isGlobalPause
}

func setRunningTask(task *STask) {
	curRunningTask = task
}

func getRunningTask() *STask {
	return curRunningTask
}

func ScheduleInit() {
	go StartSchedule()
}

func lockCore() {
	corelock.Lock()
}

func unlockCore() {
	corelock.Unlock()
}

type SCmdExecStatus int

const (
	SCmdExecStatus_Unknow             SCmdExecStatus = iota
	SCmdExecStatus_Success
	SCmdExecStatus_NotEnoughPrivilege
	SCmdExecStatus_WrongArg
	SCmdExecStatus_ErrorOther
)

type SCmdStructExecCb struct {
	Result SCmdExecStatus
}

type SCmdStruct struct {
	SCmd     SCMD
	SendTime time.Time
	Arg      []interface{}

	ExecCb func(SCmdStructExecCb)
}

func StartSchedule() {
	idleticker := time.NewTicker(2 * time.Second)
	for {
		select {
		case cmd := <-coreChan:
			coreSchedule(cmd)
		case <-idleticker.C:
			if len(coreChan) == 0 {
				SendSCmd(SCMD_SChedule, nil)
			}
		}
	}
}

func coreSchedule(cmd SCmdStruct) {
	lockCore()
	defer unlockCore()

	if cmd.SCmd > SCMD_SuperTaskStart && cmd.SCmd < SCMD_SuperTaskStartEnd {
		//Super cmd
		if stask := FindSTaskBySCmd(cmd.SCmd); stask == nil {
			log.Println(log.ErrorLog, "Can not find stask by cmd:", cmd.SCmd)
			return
		} else {
			//check cur running task
			if checkTaskCanRun(stask) == false {
				log.Println(log.DebugLog, stask.Task.GetName(), " Can not run because of upper level task running!")
				stask.Do(false, cmd.SCmd, cmd.Arg...)
				if cmd.ExecCb != nil {
					cmd.ExecCb(SCmdStructExecCb{Result: SCmdExecStatus_NotEnoughPrivilege})
				}
				return
			}

			//task is now running
			if stask.TaskStatus != TaskStatus_Running {
				interruptOtherTask(stask)
				interruptPlayer(stask.Task.GetName())
			}
			stask.SetTaskStatus(TaskStatus_Running)
			curRunningTask = stask
			log.Printf(log.DebugLog, "%s begins to run! cmd:%+v\n", stask.Task.GetName(), cmd)
			if stask.Task.GetScheduleDomain != nil {
				setscheduleDomain(stask.Task.GetScheduleDomain)
			} else {
				setscheduleDomain(scheduleDomain_default_nonemusic)
			}
			stask.Do(true, cmd.SCmd, cmd.Arg...)
			if cmd.ExecCb != nil {
				cmd.ExecCb(SCmdStructExecCb{Result: SCmdExecStatus_Success})
			}
		}
	} else if cmd.SCmd > SCMD_MusicPlayerStart && cmd.SCmd < SCMD_MusicPlayerEnd {
		//Music cmd
		isCanExec := playCheckSuperTask()
		interruptTaskByLevel(TaskLevel_Common, "player")
		//Music scene
		switch cmd.SCmd {
		case SCMD_MusicPlayer_Pause:
			isGlobalPause = false
			showIcon := true
			if len(cmd.Arg) > 0 {
				switch eType := cmd.Arg[0].(type) {
				case PlayerArg:
					isGlobalPause = eType.GloablePause
					showIcon = !eType.NotShowIcon
				default:

				}
			}

			if isCanExec == true {
				curRunningPlayer.SetInterruptStatus(false)
				curRunningPlayer.Pause(showIcon, ModuleName_UserTrig)
				if cmd.ExecCb != nil {
					cmd.ExecCb(SCmdStructExecCb{Result: SCmdExecStatus_Success})
				}
			} else {
				curRunningPlayer.PlayAfterResume = false
				if cmd.ExecCb != nil {
					cmd.ExecCb(SCmdStructExecCb{Result: SCmdExecStatus_NotEnoughPrivilege})
				}
			}
			eventPoint.PlayPauseEvent(eventPoint.ModelValPause, curRunningPlayer.GetPlayerStatus().Uuid)
		case SCMD_MusicPlayer_PlayOrPause:
			showIcon := false
			if len(cmd.Arg) == 1 {
				if notshow, ok := cmd.Arg[0].(bool); ok {
					showIcon = !notshow
				}
			} else if len(cmd.Arg) == 0 {
				showIcon = true
			}

			if isCanExec == true {
				switch curRunningPlayer.GetPlayerCategory() {
				case PlayerCategory_CommonMusic:
					isGlobalPause = curRunningPlayer.PlayOrPause(showIcon, ModuleName_UserTrig)

				case PlayerCategory_Scene:
					if curRunningPlayer.Player.PlayOrPause != nil {
						isGlobalPause = curRunningPlayer.Player.PlayOrPause()
					}
				}
				if cmd.ExecCb != nil {
					cmd.ExecCb(SCmdStructExecCb{Result: SCmdExecStatus_Success})
				}
			} else {
				if cmd.ExecCb != nil {
					cmd.ExecCb(SCmdStructExecCb{Result: SCmdExecStatus_NotEnoughPrivilege})
				}
			}

		case SCMD_MusicPlayer_Play:
			if isCanExec == true {
				switch curRunningPlayer.GetPlayerCategory() {
				case PlayerCategory_CommonMusic:
					curRunningPlayer.ForceContinuePlay()
				case PlayerCategory_Scene:
					curRunningPlayer.OemArg.StartPos = 0
					globals.SetEq(globals.ADAU1761_EQ_NORMAL)
					curRunningPlayer.Player.Play(0, curRunningPlayer.OemArg)
					curRunningPlayer.OemArg.OemArg = nil
					vui.ShowIconMusic()
				}
				if cmd.ExecCb != nil {
					cmd.ExecCb(SCmdStructExecCb{Result: SCmdExecStatus_Success})
				}
			} else {
				curRunningPlayer.PlayAfterResume = true
				if cmd.ExecCb != nil {
					cmd.ExecCb(SCmdStructExecCb{Result: SCmdExecStatus_NotEnoughPrivilege})
				}
			}

			eventPoint.PlayPauseEvent(eventPoint.ModelValPlay, curRunningPlayer.GetPlayerStatus().Uuid)
		case SCMD_MusicPlayer_RequestPlay:
			isGlobalPause = false
			isNewStart = false
			if cmd.Arg != nil && len(cmd.Arg) > 0 {
				if playerid, ok := cmd.Arg[0].(uint32); ok {
					log.Println(log.DebugLog, "Player req playerid:", playerid, ", can exec:", isCanExec)
					if player, ok := playermap[playerid]; ok && player != nil {
						if len(cmd.Arg) >= 2 {
							player.OemArg.OemArg = cmd.Arg[1]
						} else {
							player.OemArg.OemArg = nil
						}
						switch player.GetPlayerCategory() {
						case PlayerCategory_CommonMusic:
							if isCanExec {
								if curRunningPlayer != player {
									changePlayer(curRunningPlayer, player)
								}

								if curRunningPlayer != nil && curRunningPlayer.Player.GetScheduleDomain != nil {
									setscheduleDomain(curRunningPlayer.Player.GetScheduleDomain)
								} else {
									setscheduleDomain(scheduleDomain_default_player)
								}

								//uncontrol player
								if curRunningPlayer.Player.IfForcePause() == false {
									//curRunningPlayer.ClearPlayStatus()
									curRunningPlayer.StartPlay(REQUEST_PLAY_PARAMS)
								} else {
									globals.SetEq(globals.ADAU1761_EQ_NORMAL)
									misc.VolTrigeMicAdc()
									curRunningPlayer.SetActiveStatus(true)
									curRunningPlayer.SetInterruptStatus(false)
									curRunningPlayer.playerDetail.Status = globals.MUSIC_ST_PLAYING
								}

								if cmd.ExecCb != nil {
									cmd.ExecCb(SCmdStructExecCb{Result: SCmdExecStatus_Success})
								}
							} else {
								if player.Player.IfForcePause() == true {
									player.Player.Pause()
									player.playerDetail.Status = globals.MUSIC_ST_PAUSED
								}
								//player.PlayAfterResume = false
								//player.HasRequestPlayWhenInterrupt = false

								if cmd.ExecCb != nil {
									cmd.ExecCb(SCmdStructExecCb{Result: SCmdExecStatus_NotEnoughPrivilege})
								}
							}
						case PlayerCategory_Scene:
							if cmd.Arg != nil && len(cmd.Arg) >= 2 {
								if player, playerok := playermap[playerid]; playerok {
									curPlayerTmp := curRunningPlayer

									changePlayer(curRunningPlayer, player)
									if success := player.Player.EnterScene(isCanExec, cmd.Arg[1]); success != true {
										changePlayer(curRunningPlayer, curPlayerTmp)
									}
									if cmd.ExecCb != nil {
										cmd.ExecCb(SCmdStructExecCb{Result: SCmdExecStatus_Success})
									}
								} else {
									if cmd.ExecCb != nil {
										cmd.ExecCb(SCmdStructExecCb{Result: SCmdExecStatus_WrongArg})
									}
								}
							} else {
								if cmd.ExecCb != nil {
									cmd.ExecCb(SCmdStructExecCb{Result: SCmdExecStatus_WrongArg})
								}
							}
						}
					} else {
						if cmd.ExecCb != nil {
							cmd.ExecCb(SCmdStructExecCb{Result: SCmdExecStatus_WrongArg})
						}
					}
				} else {
					if cmd.ExecCb != nil {
						cmd.ExecCb(SCmdStructExecCb{Result: SCmdExecStatus_WrongArg})
					}
				}
			} else {
				if cmd.ExecCb != nil {
					cmd.ExecCb(SCmdStructExecCb{Result: SCmdExecStatus_WrongArg})
				}
			}

		case SCMD_MusicPlayer_Stop:
			if isCanExec == true {
				curRunningPlayer.Stop()
				if cmd.ExecCb != nil {
					cmd.ExecCb(SCmdStructExecCb{Result: SCmdExecStatus_Success})
				}
			} else {
				curRunningPlayer.PlayAfterResume = false
				if cmd.ExecCb != nil {
					cmd.ExecCb(SCmdStructExecCb{Result: SCmdExecStatus_NotEnoughPrivilege})
				}
			}

		case SCMD_MusicPlayer_Seek:
			if isCanExec {
				if cmd.Arg != nil && len(cmd.Arg) > 0 {
					if pos := cmd.Arg[0].(uint32); pos >= 0 {
						if pos == 0 {
							pos = 1
						}
						curRunningPlayer.Seek(pos)
					}
					if cmd.ExecCb != nil {
						cmd.ExecCb(SCmdStructExecCb{Result: SCmdExecStatus_Success})
					}
				} else {
					if cmd.ExecCb != nil {
						cmd.ExecCb(SCmdStructExecCb{Result: SCmdExecStatus_WrongArg})
					}
				}
			} else {
				if cmd.ExecCb != nil {
					cmd.ExecCb(SCmdStructExecCb{Result: SCmdExecStatus_NotEnoughPrivilege})
				}
			}

		case SCMD_MusicPlayer_PlayNext:
			if isCanExec {
				isGlobalPause = false
				if len(cmd.Arg) > 0 {
					curRunningPlayer.PlayNext(cmd.Arg[0])
				} else {
					curRunningPlayer.PlayNext(nil)
				}

				if cmd.ExecCb != nil {
					cmd.ExecCb(SCmdStructExecCb{Result: SCmdExecStatus_Success})
				}
			} else {
				if cmd.ExecCb != nil {
					cmd.ExecCb(SCmdStructExecCb{Result: SCmdExecStatus_NotEnoughPrivilege})
				}
			}

		case SCMD_MusicPlayer_PlayPre:
			if isCanExec {
				isGlobalPause = false
				if len(cmd.Arg) > 0 {
					curRunningPlayer.PlayPre(cmd.Arg[0])
				} else {
					curRunningPlayer.PlayPre(nil)
				}

				if cmd.ExecCb != nil {
					cmd.ExecCb(SCmdStructExecCb{Result: SCmdExecStatus_Success})
				}
			} else {
				if cmd.ExecCb != nil {
					cmd.ExecCb(SCmdStructExecCb{Result: SCmdExecStatus_NotEnoughPrivilege})
				}
			}

		case SCMD_Scene_Exit:
			if curRunningPlayer == nil || curRunningPlayer.GetPlayerCategory() == PlayerCategory_Scene {
				if player := playermap[uint32(globals.PlayerType_Wifi)]; player != nil {
					changePlayer(curRunningPlayer, player)
					curRunningPlayer = player
					curRunningPlayer.Resume()
					if cmd.ExecCb != nil {
						cmd.ExecCb(SCmdStructExecCb{Result: SCmdExecStatus_Success})
					}
				} else {
					if cmd.ExecCb != nil {
						cmd.ExecCb(SCmdStructExecCb{Result: SCmdExecStatus_ErrorOther})
					}
				}
			} else {
				if cmd.ExecCb != nil {
					cmd.ExecCb(SCmdStructExecCb{Result: SCmdExecStatus_ErrorOther})
				}
			}
		}
		//other scene
	} else if cmd.SCmd == SCMD_SChedule || cmd.SCmd == SCMD_MusicPlayer_Offline {
		if len(coreChan) > 0 {
			log.Println(log.DebugLog, "Re schedule continue, len:", len(coreChan))
			if cmd.ExecCb != nil {
				cmd.ExecCb(SCmdStructExecCb{Result: SCmdExecStatus_NotEnoughPrivilege})
			}
			return
		}
		//start := time.Now()
		reCheckScheduleTask()
		if cmd.ExecCb != nil {
			cmd.ExecCb(SCmdStructExecCb{Result: SCmdExecStatus_Success})
		}
		//log.Println(log.DebugLog, "Auto schedule finish, cost time:", time.Now().Sub(start)/time.Microsecond)
	} else if cmd.SCmd == SCMD_KeyInterrupt {
		interruptTaskByKey()
		if cmd.ExecCb != nil {
			cmd.ExecCb(SCmdStructExecCb{Result: SCmdExecStatus_Success})
		}
	}
}

func playCheckSuperTask() (canPlay bool) {
	for i := TaskLevel_Min; i < TaskLevel_Common; i++ {
		//for _, levelTasks := range alltask {
		for _, task := range alltask[i] {
			if task.Task.IsActive() == true {
				log.Println(log.DebugLog, "Task is running:", task.Task.GetName())
				return false
			}
		}
	}
	curRunningTask = nil
	return true
}

func interruptOtherTask(besidesTask *STask) {
	for i := besidesTask.Task.GetTaskLevel(); i < TaskLevel_MAX; i++ {
		for _, stask := range alltask[i] {
			if stask.Task.GetName() == besidesTask.Task.GetName() {
				continue
			}

			if stask.Task.GetTaskLevel() == besidesTask.Task.GetTaskLevel() {
				stask.Task.Interrupt(besidesTask.Task.GetName())
			} else {
				stask.Interrupt(besidesTask.Task.GetName())
			}
		}
	}
}

func interruptTaskByLevel(level TaskLevel, byWho string) {
	for _, stask := range alltask[level] {
		stask.Interrupt(byWho)
	}
}

func interruptPlayer(byname string) {
	if curRunningPlayer == nil {
		curRunningPlayer = playermap[uint32(globals.PlayerType_Wifi)]
	}

	if curRunningPlayer != nil {
		eventPoint.SetEpOsSouce("F141", eventPoint.EpOs_Device)
		curRunningPlayer.Interrupt(byname)
	}

	vui.ClearIconMusic()
}

func interruptTaskByKey() {
	for _, levelTasks := range alltask {
		for _, tks := range levelTasks {
			if tks.BeInterruptedByKey() == true {
				tks.Interrupt(ModuleName_Key)
			}
		}
	}
}

//poll and check task status
func reCheckScheduleTask() {
	defer func() {
		if err := recover(); err != nil {
			log.Println(log.ErrorLog, "err:", err)
		}
	}()
	for _, levelTasks := range alltask {
		for _, tks := range levelTasks {
			if tks.Task.IsActive() {
				globals.UpdateActiveTime()
				if tks.GetTaskStatus() != TaskStatus_Running {
					tks.SetTaskStatus(TaskStatus_Running)
					curRunningTask = tks
					log.Println(log.DebugLog, "Begin to resume ", tks.Task.GetName())
					interruptOtherTask(tks)
					interruptPlayer(tks.Task.GetName())
					tks.Resume()

					if tks.Task.IsActive() == false {
						tks.SetTaskStatus(TaskStatus_Init)
						curRunningTask = nil
						log.Println(log.DebugLog, tks.Task.GetName(), " finish, schedule next!")
						continue
					} else {
						//task is running
						return
					}
				} else {
					//do nothing, task is running!
					curRunningTask = tks
				}
				//log.Println(log.DebugLog, "Task Schedule, cur running:", tks.Task.GetName())
				return
			} else {
				switch(tks.GetTaskStatus()) {
				case TaskStatus_Running:
					tks.SetTaskStatus(TaskStatus_Init)
					if curRunningTask == tks {
						curRunningTask = nil
					}
				case TaskStatus_Interrupted:
					tks.SetTaskStatus(TaskStatus_Init)
				}
			}
		}
	}
	curRunningTask = nil

	//come here means task is nil, can play
	if curRunningPlayer != nil && curRunningPlayer.Player.GetScheduleDomain != nil {
		setscheduleDomain(curRunningPlayer.Player.GetScheduleDomain)
	} else {
		setscheduleDomain(scheduleDomain_default_player)
	}

	if curRunningPlayer.Player.IsOnline() {
		if result := curRunningPlayer.Resume(); result == true && globals.CurBootState == globals.BootStage_FINISH {
			globals.IconLedMusicPlayMode.ForceCallCb()
		}

		if curRunningPlayer.IsPlaying() {
			globals.UpdateActiveTime()
		}
	} else {
		//curplayer is offline, change to the wifi player
		if curRunningPlayer.GetPlayerId() != uint32(globals.PlayerType_Wifi) {
			prevPlayer := curRunningPlayer.GetPlayerId()
			if player := playermap[uint32(globals.PlayerType_Wifi)]; player != nil {
				changePlayer(curRunningPlayer, player)
				curRunningPlayer = player

				if curRunningPlayer != nil && curRunningPlayer.Player.GetScheduleDomain != nil {
					setscheduleDomain(curRunningPlayer.Player.GetScheduleDomain)
				}

				if isGlobalPause == true {
					log.Println(log.DebugLog, "Global pause is ", isGlobalPause)
					isGlobalPause = false
					curRunningPlayer.PlayAfterResume = false
				}

				if prevPlayer != uint32(globals.PlayerType_Bt){   //PV1-2041 //PV1-4131
					curRunningPlayer.PlayAfterResume = false
				}

				curRunningPlayer.Resume()
			}
		}
	}

	if curRunningPlayer.IsPlaying() == true {
		vui.ShowIconMusic()
		misc.VolTrigeMicAdc()
		globals.SetEq(globals.ADAU1761_EQ_NORMAL)
	} else {
		vui.ClearIconMusic()
		//misc.IdleMicAdc()
		TryMicAdcIdle()
	}
}

func changePlayer(from *SPlayer, to *SPlayer) {
	log.Println(log.DebugLog, from.Player.GetPlayerName(), " jumps to ", to.Player.GetPlayerName())
	globals.ClearCurPlayerSt(globals.PlayerType(to.GetPlayerId()))

	if from == to {
		log.Println(log.DebugLog, "from eq to, do nothing!")
		return
	}

	if from == nil || to == nil {
		log.Println(log.DebugLog, "Player is nil !!Change player exit!")
		return
	}

	from.SetPlayerChange(true)
	if from.Player.PlayerChangeCb != nil {
		from.Player.PlayerChangeCb(false)
	}
	to.SetPlayerChange(true)
	if to.Player.PlayerChangeCb != nil {
		to.Player.PlayerChangeCb(true)
	}

	from.Interrupt(to.Player.GetPlayerName())
	curRunningPlayer = to

	//todo just for test
	if globals.PlayerType(from.GetPlayerId()) == globals.PlayerType_Bt ||
		globals.PlayerType(from.GetPlayerId()) == globals.PlayerType_Airplay {
		from.SetInterruptStatus(false)
	}

	from.SetActiveStatus(false)
	to.SetActiveStatus(true)

	if globals.PlayerType(to.GetPlayerId()) == globals.PlayerType_Wifi {
		uuid := to.GetPlayerStatus().Uuid
		if "" != uuid {
			globals.CurPlayerSt.ContinuousTaskSt = to.GetPlayerStatus().Status
			globals.CurPlayerSt.PlayerId = globals.PlayerType(to.Id)
			globals.CurPlayerSt.MusicId = &uuid
			globals.CurPlayerSt.CurPlayingPos = to.GetPlayerStatus().CurPos
			globals.CurPlayerSt.Duration = to.GetPlayerStatus().Duration
		} else {
			isNewStart = true
		}
	}

	if from.GetPlayerCategory() == PlayerCategory_Scene {
		LockScene()
		curscene = nil
		UnlockScene()
	}

	curRunningPlayer = to
	globals.ResetBroadCastTimer()
}

func checkTaskCanRun(task *STask) (canRun bool) {
	for i := TaskLevel_Min; i <= task.Task.GetTaskLevel() && i < TaskLevel_MAX; i++ {
		for _, tmptask := range alltask[i] {
			if tmptask.Task.GetName() == task.Task.GetName() {
				continue
			}

			if i == task.Task.GetTaskLevel() {
				if tmptask.Task.IsActive() == true {
					if tmptask.Task.CanBeInterruptBySameLevelTask == nil || tmptask.Task.CanBeInterruptBySameLevelTask != nil && tmptask.Task.CanBeInterruptBySameLevelTask() == false {
						return false
					}
				}
			} else {
				if tmptask.Task.IsActive() == true {
					return false
				}
			}
		}
	}

	return true
}

func CheckTaskActive(level TaskLevel) (isActive bool) {
	for i := TaskLevel_Min; i <= level; i++ {
		for _, task := range alltask[i] {
			if task.Task.IsActive() == true {
				return true
			}
		}
	}

	return false
}

func playerRequestPlay(playerid uint32, arg interface{}) (canPlay bool) {
	lockCore()
	defer unlockCore()

	isCanExec := playCheckSuperTask()
	if isCanExec == true {
		interruptTaskByLevel(TaskLevel_Common, "player_request_sync")
	}
	log.Println(log.DebugLog, "Request play, can exec:", isCanExec)
	if isMusicMode {
		if player, ok := playermap[playerid]; ok && player != nil {
			if isCanExec {
				if curRunningPlayer != player {
					changePlayer(curRunningPlayer, player)
				}

				if curRunningPlayer != nil && curRunningPlayer.Player.GetScheduleDomain != nil {
					setscheduleDomain(curRunningPlayer.Player.GetScheduleDomain)
				} else {
					setscheduleDomain(scheduleDomain_default_player)
				}

				curRunningPlayer.OemArg.OemArg = arg
				//uncontrol player
				if curRunningPlayer.Player.IfForcePause() == false {
					//curRunningPlayer.ClearPlayStatus()
					curRunningPlayer.StartPlay(REQUEST_PLAY_PARAMS)
				} else {
					curRunningPlayer.SetActiveStatus(true)
					curRunningPlayer.SetInterruptStatus(false)
					curRunningPlayer.playerDetail.Status = globals.MUSIC_ST_PLAYING
					vui.ShowIconMusic()
				}
			} else {
				if player.Player.IfForcePause() == true {
					player.Player.Pause()
					player.playerDetail.Status = globals.MUSIC_ST_PAUSED
				}
				//player.PlayAfterResume = false
				//player.HasRequestPlayWhenInterrupt = false
			}

			// wait for st from player
			time.Sleep(100 * time.Millisecond)

			return true
		} else {
			log.Printf(log.ErrorLog, "playerid:%d req play, but not find the player!\n", playerid)
			return false
		}
	}

	return false
}
