package player

import (
	"encoding/json"
	"fmt"
	. "netease_control_center/globals"
	"netease_control_center/interfaces"
	"netease_control_center/interfaces/eventPoint"
	"netease_control_center/interfaces/log"
	. "netease_control_center/interfaces/schedule"
	"netease_control_center/interfaces/vui"
	"time"
)

const (
	DLNA_PLAYER_NAME = "dlna_player"
	DLNA_SET_ARG_LEN = 1

	CTRL_DLNA_STOP    = "OnStop"
	CTRL_DLNA_PLAY    = "OnPlay"
	CTRL_DLNA_PAUSE   = "OnPause"
	CTRL_DLNA_NEXT    = "OnNext"
	CTRL_DLNA_ZEROING = "OnZero" //for qq music PV1-3158

	DLNA_PORT = 5005
)

type CtrlDlna struct {
	Action string `json:"action"`
	Val    int    `json:"val"`
}

var (
	DlnaPlaySeek bool = false

	//dlnaPlayerName = "DLNA_"

	//oldDlnaStatusIsPlaying bool = false

	dlnaNeedSeekPos bool = false
	dlnaSeekPos     uint32

	dlnaIsOnline bool = false
	dlnaHasSetrg bool = false
	dlnaPlayArg  interface{}

	dlnaUrl            *string
	dlnaBgUrl          *string = nil
	dlnaPlayPauseState bool    = false //false->pause  true->play

	dlnaErrTimer      *time.Timer = nil
	dlnaWaitNextTimer *time.Timer = nil

	// 音乐播放状态变化时，需要更新
	dlnaPlayerSt = PlayerStatus{PlayerSrc: DLNA_SRC, MusicId: nil, MusicListId: nil, ContinuousTaskSt: MUSIC_ST_IDLE, CurPlayingPos: 0,
		TaskField:    FIELD_NULL,
		SingleTaskSt: AUDIO_ST_IDLE}
)

func DlnaStartTrig() {
	dlnaIsOnline = true
}
func DlnaStopTrig() {
	SetDlnaPlayPauseState(false)
	dlnaIsOnline = false
	ClearProjectorVolProcess()
	PlayerHander[PlayerType_Dlna].ReportOffline()
}

func SetDlnaPlayPauseState(st bool) {
	dlnaPlayPauseState = st
}

func GetDlnaPlayPauseState() bool {
	return dlnaPlayPauseState
}

func DlnaPause() {
	sendMusicCmd(PlayerType_Dlna, CMD_PLAYER_PAUSE)
	if !GetDlnaPlayPauseState() {
		SetDlnaPlayPauseState(false)
	} else {
		SetDlnaPlayPauseState(false)
		if PlayerHander[PlayerType_Dlna].IsPlaying() {
			//isChange := PlayerHander[PlayerType_Dlna].IsPlayerChange(false)
			//log.Printf(log.WarningLog, "ischange:%+v\n", isChange)
			//if isChange {
			//	CtrlDlnaCmdToPhone(CTRL_DLNA_STOP)
			//} else {
			DlnaPlaySeek = true
			CtrlDlnaCmdToPhone(CTRL_DLNA_PAUSE)
			//}
		} else {
			log.Println(log.WarningLog, "dlna is not playing, ignore pause to phone.")
		}
	}

}

func DlnaPlay(start int, arg SCmd_Args) bool {
	if DlnaPlaySeek {
		DlnaPlaySeek = false
		dlnaNeedSeekPos = true
		dlnaSeekPos = dlnaPlayerSt.CurPlayingPos
		log.Println(log.WarningLog, "dlnaSeekPos:", dlnaSeekPos)
	}

	log.Println(log.WarningLog, "start:", start)
	if dlnaHasSetrg {
		log.Println(log.WarningLog, "dlnaHasSetrg:", dlnaHasSetrg)
		dlnaHasSetrg = false
		dlnaPlayApi(dlnaPlayArg)
		return true
	} else {
		isChange := PlayerHander[PlayerType_Dlna].IsPlayerChange(true)
		//sendMusicCmd(PlayerType_Dlna, CMD_PLAYER_PLAY)
		log.Printf(log.DebugLog, "\nstatus:%+v ,isChange:%d\n",
			PlayerHander[PlayerType_Dlna].GetPlayerStatus(),
			isChange)
		if isChange {
			// 拉取url重新播放
			songId := PlayerHander[PlayerType_Dlna].GetPlayerStatus().Uuid
			dlnaPlayApi(&songId, &songId)

			if PLAY_FROM_START_POS != start {
				// 收到play的消息后， 需要seek到指定位置
				dlnaNeedSeekPos = true
				dlnaSeekPos = uint32(start)
			} else {
				CtrlDlnaCmdToPhone(CTRL_DLNA_ZEROING)
			}
		} else {
			if PLAY_FROM_START_POS == start {
				// 拉去url重新播放
				CtrlDlnaCmdToPhone(CTRL_DLNA_ZEROING)
				songId := PlayerHander[PlayerType_Dlna].GetPlayerStatus().Uuid
				dlnaPlayApi(&songId, &songId)
			} else {
				// 直接发送播放命令
				dlnaPlayApi()
			}
		}

		return true
	}
}

func DlnaStop() {
	sendMusicCmd(PlayerType_Dlna, CMD_PLAYER_PAUSE)
	DlnaPlaySeek = false
	CtrlDlnaCmdToPhone(CTRL_DLNA_STOP)
	SetDlnaPlayPauseState(false)
}

func DlnaSeek(pos uint32) {
	sendMusicCmd(PlayerType_Dlna, CMD_PLAYER_SEEKTO, pos*1000)
}

func DlnaIsOnline() bool {
	//
	return dlnaIsOnline
}

func DlnaIfForcePause() bool {

	return false
}

func DlnaPlayNext(arg interface{}) {
	// nil
}

func DlnaPlayPre(arg interface{}) {
	// nil
}

func DlnaPrepareNext() {
	// nil
}

func DlnaGetSUpportedSCmd() []SCMD {

	return nil
}

func DlnaSetArg(arg ...interface{}) bool {
	if DLNA_SET_ARG_LEN == len(arg) {
		switch arg0 := arg[0].(type) {
		case *string:
			dlnaPlayArg = arg0
		default:
			log.Println(log.ErrorLog, "arg0:", arg0)
			goto errOut
		}
		dlnaHasSetrg = true
		return true
	} else {
		log.Println(log.ErrorLog, "len:", len(arg))
	}
errOut:
	log.Printf(log.ErrorLog, "err arg params:%+v\n", arg)
	dlnaHasSetrg = false
	return false
}

func DlnaGetPlayerName() string {
	return DLNA_PLAYER_NAME
}

func DlnaPlayerChange(in bool) {
	if !in {
		ClearProjectorVolProcess()
		//DLNAOff()
		log.Println(log.WarningLog, "Dis DLNA by vbox")
	}
}

func StopDlnaWaitNextTimer() {
	if nil != dlnaWaitNextTimer {
		dlnaWaitNextTimer.Stop()
		dlnaWaitNextTimer = nil
	}
}

func DlnaPlayerStatusChange(status PlayerDetail) {
	switch status.Status {
	case MUSIC_ST_PLAYING:
		if "" != status.Uuid {
			if dlnaNeedSeekPos {
				dlnaNeedSeekPos = false
				sendMusicCmd(PlayerType_Dlna, CMD_PLAYER_SEEKTO, dlnaSeekPos)
			}

			updateDlnaPlayerStatus(status)

			if ttsMusicUuid != status.Uuid {
				ttsNoMusic = false
			}
		}
	case MUSIC_ST_IDLE, MUSIC_ST_PAUSED, MUSIC_ST_COMPLETED, MUSIC_ST_PREPARING:
		if MUSIC_ST_COMPLETED == status.Status {
			if nil != dlnaWaitNextTimer {
				dlnaWaitNextTimer.Stop()
			}
			dlnaWaitNextTimer = time.AfterFunc(DlnaWaitNextTime.GetCfgListTime(), func() {
				DlnaStopTrig()
				//CtrlDlnaCmdToPhone(CTRL_DLNA_NEXT)
				log.Printf(log.WarningLog, "wait dlna next timeout\n")
			})
		}

		if "" != status.Uuid {
			status.CurPos = 0 // play end, reset curpos to 0
			log.Println(log.DebugLog, "DlnaPlayerStatusChange set CurPos to 0")
			updateDlnaPlayerStatus(status)
		}
	case PLAYER_ERR_TINA_NOTIFY, PLAYER_ERR_TINA_START, PLAYER_ERR_TINA_RESET,
		PLAYER_ERR_TINA_SETSOURCE, PLAYER_ERR_TINA_PREPARE:
		log.Println(log.DebugLog, "...tinaplayer err...", status.Status)

		if nil != dlnaErrTimer {
			dlnaErrTimer.Stop()
		}

		DlnaPlaySeek = false
		dlnaErrTimer = time.AfterFunc(500*time.Millisecond, func() {
			dlnaErrTimer = nil

			log.Printf(log.ErrorLog, "st:%+v\n", PlayerHander[PlayerType_Dlna].GetPlayerStatus())
			if PlayerHander[PlayerType_Dlna].IsPlaying() {
				log.Println(log.DebugLog, "...tinaplayer err...but player is playing")
			} else {
				//DlnaPlayNext()
				CtrlDlnaCmdToPhone(CTRL_DLNA_PAUSE)
				SetDlnaPlayPauseState(false)
				//NoticePlayerSendSCmd(SCMD_SuperTask_Tts_Play, TTS_DLNA_ERR_1, CONST_AUDIO_ID, AdSrcType_TTS, TTS_LEVEL_1,
				//	true, false)
				mscToastTts(TTS_DLNA_ERR_1, CONST_AUDIO_ID, true, false, nil)
			}
		})
	case PLAYER_ERR_TINA_SEEKTO:
		log.Println(log.WarningLog, "tina play seek err:", status.Status)
	case MUSIC_ST_PREPARING_TIMEOUT:
		log.Println(log.ErrorLog, "dlna perparing timeout")
		//NoticePlayerSendSCmd(SCMD_SuperTask_Tts_Play, vui.SoundNotice_Song_Get_Timeout.GetPath(), CONST_AUDIO_ID, AdSrcType_FILE, TTS_LEVEL_1,
		//	true, false)
		mscToastFile(vui.SoundNotice_Song_Get_Timeout.GetPath(), CONST_AUDIO_ID, true, false, nil)
		CtrlDlnaCmdToPhone(CTRL_DLNA_PAUSE)
		SetDlnaPlayPauseState(false)
		eventPoint.PrepareTimeout(PlayerType_Dlna, status.Uuid)
	case MUSIC_ST_PREPARED:
		log.Println(log.DebugLog, "prepared")
	case MUSIC_ST_FOR_NEXT:
		log.Println(log.DebugLog, "prepared next, but dlna do nothing")
	default:
		//oldDlnaStatusIsPlaying = false

		log.Printf(log.WarningLog, "invalid st:0x%x\n", status.Status)
	}
}

func CtrlDlnaCmdToPhone(cmd string) {
	var tmp CtrlDlna
	tmp.Action = cmd
	data, err := json.Marshal(tmp)
	if nil != err {
		log.Println(log.ErrorLog, err)
		return
	}
	log.Println(log.DebugLog, string(data))
	interfaces.SendCommand(MODULE_CONTROLLER, MODULE_DLNA, CMD_KPLAYER_HOST_ACTION, &data)
}

func DLNAOn() {
	log.Printf(log.DebugLog, "cmd to on dlna.\n")
	var tmp struct {
		Name string `json:"dev"`
		Port int    `json:"port"`
	}
	//tmp.Name = dlnaPlayerName + BTNAME  //jira pv1-32
	tmp.Name = BTNAME
	tmp.Port = DLNA_PORT
	if data, err := json.Marshal(tmp); nil == err {
		interfaces.BroadSignalAll(MODULE_CONTROLLER, CMD_KPLAYER_START,
			string(data))
	} else {
		log.Println(log.DebugLog, err.Error())
		interfaces.BroadSignalAll(MODULE_CONTROLLER, CMD_KPLAYER_START,
			"")
	}
}

func DLNAOff() {
	log.Println(log.DebugLog, "cmd to off dlna")

	interfaces.BroadSignalAll(MODULE_CONTROLLER, CMD_KPLAYER_STOP,
		"")
}

func dlnaPlayApi(arg ...interface{}) {
	defer func() {
		if err := recover(); err != nil {
			log.Println(log.ErrorLog, err)
		}
	}()

	SetDlnaPlayPauseState(true)

	var urlMsg struct {
		Url string `json:"url"`
	}
	if 0 == len(arg) {
		sendMusicCmd(PlayerType_Dlna, CMD_PLAYER_PLAY)
	} else if 1 == len(arg) {
		// params: json string
		switch argVal := arg[0].(type) {
		case *string:
			err := json.Unmarshal([]byte(*argVal), &urlMsg)
			if nil != err {
				log.Println(log.DebugLog, err)
				return
			}
			dlnaUrl = &urlMsg.Url
			log.Println(log.DebugLog, "url:", *dlnaUrl)

			if nil != dlnaUrl {
				sendMusicCmd(PlayerType_Dlna, CMD_PLAYER_PLAY, dlnaUrl, dlnaUrl, nil, AdSrcType_FILE, uint32(0), float32(0), dlnaBgUrl) // dlna 的duration暂时不处理
				dlnaUrl = nil
			} else {
				sendMusicCmd(PlayerType_Dlna, CMD_PLAYER_PLAY)
			}
		default:
			log.Println(log.WarningLog, "err params type")
		}
	} else if 2 == len(arg) {
		// params: songId *string , songUrl *string
		sendMusicCmd(PlayerType_Dlna, CMD_PLAYER_PLAY, arg[0].(*string), arg[1].(*string), nil, AdSrcType_FILE, uint32(0), float32(0), dlnaBgUrl)
	}
}

func updateDlnaPlayerStatus(status PlayerDetail) uint8 {
	if status.Status < MUSIC_ST_MAX {
		dlnaPlayerSt.PlayerSrc = CurPlayerSrc
		// 连续任务状态
		dlnaPlayerSt.MusicId = &status.Uuid
		dlnaPlayerSt.ContinuousTaskSt = status.Status
		dlnaPlayerSt.CurPlayingPos = status.CurPos
		dlnaPlayerSt.MusicListId = PlayListSrcRec.MusicListId
		dlnaPlayerSt.Duration = status.Duration
		dlnaPlayerSt.ContinuousStChangeTime = time.Now()
		dlnaPlayerSt.Type = PlayListSrcRec.MusicSrc
		dlnaPlayerSt.TaskField = FIELD_MUSIC
	} else if status.Status < AUDIO_ST_MAX && status.Status >= AUDIO_ST_IDLE {
		dlnaPlayerSt.PlayerSrc = WIFI_SRC
		dlnaPlayerSt.SingleTaskSt = status.Status
		dlnaPlayerSt.SingleStChangeTime = time.Now()
	}

	var precent uint8
	if 0 == dlnaPlayerSt.Duration {
		precent = 0
	} else {
		precent = uint8(dlnaPlayerSt.CurPlayingPos * 100 / dlnaPlayerSt.Duration)
	}

	var printStr string = ""
	//if nil != dlnaPlayerSt.MusicId && len(*dlnaPlayerSt.MusicId) > 0 {
	//	printStr += fmt.Sprintf("musicId:%s ", *dlnaPlayerSt.MusicId)
	//}
	if nil != dlnaPlayerSt.MusicListId && len(*dlnaPlayerSt.MusicListId) > 0 {
		printStr += fmt.Sprintf("listId:%s ", *dlnaPlayerSt.MusicListId)
	}
	printStr += fmt.Sprintf("sSt:0x%x field:%d cSt:0x%x cur:%ds dur:%ds src:%d id:%d(%d%%)",
		dlnaPlayerSt.SingleTaskSt,
		dlnaPlayerSt.TaskField,
		dlnaPlayerSt.ContinuousTaskSt,
		status.CurPos/1000,
		status.Duration/1000,
		dlnaPlayerSt.PlayerSrc,
		PlayerType_Dlna,
		precent)
	if MUSIC_ST_PLAYING == status.Status {
		fmt.Printf("%s\r", printStr)
	} else {
		fmt.Printf("%s\n", printStr)
	}
	return precent
}
