package player

import (
	"fmt"
	. "netease_control_center/globals"
	"netease_control_center/interfaces/http"
	"netease_control_center/interfaces/log"
	. "netease_control_center/interfaces/schedule"
	_ "netease_control_center/interfaces/vui"
	"time"
)

const (
	NORMAL_PLAYER_NAME = "normal_player"
	NORMAL_SET_ARG_LEN = 2
)

var (
	normalNeedSeekToPos bool = false // 在重新拉取url播放的情况下，需要在播放回调的时候，seek到制定位置
	normalSeekPos       uint32

	normalHasSetrg bool = false
	normalPlayArg  interface{}

	needForcePauseNormalPlayer   bool = false
	autoStopPlayWhenListPlayOnce bool = false
	normalPlayerIsOnLine         bool = false

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

func NormalPause() {
	sendCurPlayerMusicCmd(CMD_PLAYER_PAUSE)
}

func NormalPlay(start int, arg SCmd_Args) bool {
	if REQUEST_PLAY_PARAMS == start {
		ttsNoMusic = false
		if normalHasSetrg {
			normalHasSetrg = false
			normalPlayApi(normalPlayArg)
			normalPlayerIsOnLine = true
			return true
		} else {
			log.Println(log.ErrorLog, "hasSetNormalArg false")
			return false
		}
	} else {
		isChange := PlayerHander[PlayerType_Other].IsPlayerChange(true)
		log.Printf(log.DebugLog, "\nstatus:%+v, isPlayerChange:%d\n",
			PlayerHander[PlayerType_Other].GetPlayerStatus(),
			isChange)
		if isChange {
			// 拉取url重新播放
			songId := PlayerHander[PlayerType_Other].GetPlayerStatus().Uuid
			songInfo := SongInfo{Id: songId, Duration: PlayerHander[PlayerType_Other].GetPlayerStatus().Duration}
			normalPlayApi(&songInfo)
			if PLAY_FROM_START_POS != start {
				// 收到play的消息后， 需要seek到指定位置
				normalNeedSeekToPos = true
				normalSeekPos = uint32(start)
			}
		} else {
			if PLAY_FROM_START_POS == start {
				// 拉去url重新播放
				songId := PlayerHander[PlayerType_Other].GetPlayerStatus().Uuid
				songInfo := SongInfo{Id: songId, Duration: PlayerHander[PlayerType_Other].GetPlayerStatus().Duration}
				normalPlayApi(&songInfo)
			} else {
				// 直接发送播放命令
				normalPlayApi(nil)
			}
		}
		normalPlayerIsOnLine = true
		return true
	}
}

func NormalStop() {
	sendCurPlayerMusicCmd(CMD_PLAYER_STOP)
}

func NormalSeek(pos uint32) {
	sendCurPlayerMusicCmd(CMD_PLAYER_SEEKTO, pos)
}

func NormalIsOnline() bool {
	return normalPlayerIsOnLine
}

func NormalIfForcePause() bool {
	// 是否需要强制暂停，返回false，只有在蓝牙这种系统控制播放的场景，才需要设置为true
	return false
}

func NormalPlayNext(arg interface{}) {
	normalNextApi(false, arg)
}

func NormalPlayPre(arg interface{}) {
	normalPreApi(arg)
}

func NormalPrepareNext() {
}

func NormalGetSUpportedSCmd() []SCMD {

	return nil
}

func NormalSetArg(arg ...interface{}) bool {
	if NORMAL_SET_ARG_LEN == len(arg) {
		switch arg[0].(type) {
		case *ServerMusicList:
			normalPlayArg = arg[0]
		default:
			log.Println(log.ErrorLog, "arg0:", arg[0])
			goto errOut
		}

		switch arg1 := arg[1].(type) {
		case bool:
			autoStopPlayWhenListPlayOnce = arg1
		default:
			log.Println(log.ErrorLog, "arg1:", arg1)
			goto errOut
		}
		normalHasSetrg = true
		return true
	} else {
		log.Println(log.ErrorLog, "len:", len(arg))
	}
errOut:
	log.Printf(log.ErrorLog, "err arg params:%+v\n", arg)
	normalHasSetrg = false
	return false
}

func NormalGetPlayerName() string {
	return NORMAL_PLAYER_NAME
}

func NormalPlayerStatusChange(status PlayerDetail) {
	normalPlayerStHd(status)
}

func normalPlayApi(e interface{}) {
	if nil == e {
		sendCurPlayerMusicCmd(CMD_PLAYER_PLAY)
		return
	}

	switch param := e.(type) {
	case *ServerMusicList:
		normalListPlay(e)
	case *SongInfo:
		lowLevelPlayApi(commonPlayApiArg{
			prepare:            false,
			songId:             param,
			songUrl:            nil,
			tts:                "",
			ttsUrl:             "",
			ttsNow:             true,
			needChangeNHDIndex: false,
			srcType:            SINGLE_SONG,
			rspId:              "",
		})
	default:
		log.Println(log.WarningLog, "err type of play")
	}
}

func normalPreApi(arg interface{}) (MusicChangeAction, error) {
	defer func() {
		if playerRecoverLevel <= MIDDLE_RECOVER_LEVEL {
			if err := recover(); err != nil {
				log.Println(log.ErrorLog, err)
			}
		}
	}()

	var rspId string = ""
	var tts, ttsUrl string = "", ""
	switch eVal := arg.(type) {
	case PlayerArg:
		rspId = eVal.RspId
		tts = eVal.InnerTts
		ttsUrl = eVal.InnerTtsUrl
	default:

	}

	if nil == LocalMusicList[OTHERS_MUSIC_LIST].GetCurPos() {
		NoticePlayerSendSCmd(SCMD_SuperTask_Tts_Play, List_ERR_NULL.Error(), CONST_AUDIO_ID, AdSrcType_TTS, TTS_LEVEL_1, true, false)
		return ACTION_NULL, List_ERR_NULL
	}
	action := getNextPrevActionByNormalPlayer(false)
	if UintTest {
		return action, nil
	}

	var songId *SongInfo = nil
	var songUrl *string = nil

	var index MusicLenType = 0
	switch action {
	case ACTION_NULL:
		// 当前列表空
	case ACTION_PLAY_DIRECT:
		LocalMusicList[OTHERS_MUSIC_LIST].GetValidPre()
	case ACTION_PLAY_BACK:
		tmpCurPos, err := LocalMusicList[OTHERS_MUSIC_LIST].GetLast()
		if nil != err {
			log.Println(log.ErrorLog, err.Error())
			return ACTION_NULL, err
		}
		LocalMusicList[OTHERS_MUSIC_LIST].SetCurPos(tmpCurPos)

		if LocalMusicList[OTHERS_MUSIC_LIST].GetCurPos().Value.(*SongInfo).CanPlay {

		} else {
			LocalMusicList[OTHERS_MUSIC_LIST].GetValidPre()
		}
	case ACTION_NEXT_PAGE_REPLACE_LIST, ACTION_MISS_PAGE_REPLACE_LIST, ACTION_LAST_PAGE:
		if ACTION_NEXT_PAGE_REPLACE_LIST == action {
			// 还有剩余分页，拉取分页
			if val, err := NormalListMap[OTHERS_LIST_PAGE].GetLast(); nil == err {
				index = val.Value.(*PageNode).PageIndex * PAGE_SIZE
			}
		} else if ACTION_MISS_PAGE_REPLACE_LIST == action {
			// 有缺失的分页，拉取分页
			index = (NormalListMap[OTHERS_LIST_PAGE].GetMissPage() - 1) * PAGE_SIZE
		} else {
			// 分页全部拉取完毕，重新拉取第一页
			NormalListMap[OTHERS_LIST_PAGE].Init()
		}

		srcType := getMusicSrcType(PlayerType_Other)
		list, err := GetMusicListNew(PlayerType_Other, true, http.MusicListServerType{
			Src:     srcType,
			Id:      getServiceId(srcType),
			Params:  getServiceParams(srcType),
			Start:   index,
			Size:    PAGE_SIZE,
			WantTts: true,

			Oftag:        NormalPlayerListSrc.TagName,
			OftagForShow: NormalPlayerListSrc.TagNameShow,
			Mode:         CurPlayingMode,
			CloudId:      NormalPlayerListSrc.CloudId,
			ModeId:       NormalPlayerListSrc.ModeId,
		})
		//list, err := getMusicList(PlayerType_Other, srcType, getServiceId(srcType),
		//	getServiceParams(srcType), index, PAGE_SIZE, true, CurPlayingMode)
		if nil != err {
			log.Println(log.ErrorLog, err.Error())
			return ACTION_NULL, err
		}
		updateNormalPlayListAndPage(list, index, true)

		tmpCurPos, err := LocalMusicList[OTHERS_MUSIC_LIST].GetLast()
		if nil != err {
			log.Println(log.ErrorLog, err.Error())
			return ACTION_NULL, err
		}
		LocalMusicList[OTHERS_MUSIC_LIST].SetCurPos(tmpCurPos)

		if LocalMusicList[OTHERS_MUSIC_LIST].GetCurPos().Value.(*SongInfo).CanPlay {

		} else {
			LocalMusicList[OTHERS_MUSIC_LIST].GetValidPre()
		}
	default:
		log.Println(log.WarningLog, "err action")
		return ACTION_NULL, Normal_ERR_ACTION
	}
	if ACTION_NULL != action {
		songId = LocalMusicList[OTHERS_MUSIC_LIST].GetCurPos().Value.(*SongInfo)
	}

	return action, lowLevelPlayApi(commonPlayApiArg{
		prepare:            false,
		songId:             songId,
		songUrl:            songUrl,
		tts:                tts,
		ttsUrl:             ttsUrl,
		ttsNow:             true,
		needChangeNHDIndex: false,
		srcType:            NormalPlayerListSrc.MusicSrc,
		rspId:              rspId,
	})
}

func normalNextApi(prepare bool, arg interface{}) (MusicChangeAction, error) {
	defer func() {
		if playerRecoverLevel <= MIDDLE_RECOVER_LEVEL {
			if err := recover(); err != nil {
				log.Println(log.ErrorLog, err)
			}
		}
	}()

	var rspId string = ""
	var tts, ttsUrl string = "", ""
	switch eVal := arg.(type) {
	case PlayerArg:
		rspId = eVal.RspId
		tts = eVal.InnerTts
		ttsUrl = eVal.InnerTtsUrl
	default:

	}

	if nil == LocalMusicList[OTHERS_MUSIC_LIST].GetCurPos() {
		NoticePlayerSendSCmd(SCMD_SuperTask_Tts_Play, List_ERR_NULL.Error(), CONST_AUDIO_ID, AdSrcType_TTS, TTS_LEVEL_1, true, false)
		return ACTION_NULL, List_ERR_NULL
	}
	action := getNextPrevActionByNormalPlayer(true)
	if UintTest {
		return action, nil
	}

	var index MusicLenType = 0
	var songId *SongInfo = nil
	var songUrl *string = nil

	switch action {
	case ACTION_NULL:
		// 当前列表空
	case ACTION_STOP_PLAYER:
		log.Printf(log.DebugLog, "normal player auto stop.\n")
		normalPlayerIsOnLine = false
		PlayerHander[PlayerType_Other].ReportOffline()
		// todo normal play auto stop, process your things

		return ACTION_STOP_PLAYER, nil
	case ACTION_PLAY_DIRECT:
		LocalMusicList[OTHERS_MUSIC_LIST].GetValidNext()
		songId = LocalMusicList[OTHERS_MUSIC_LIST].GetCurPos().Value.(*SongInfo)
	case ACTION_PLAY_FRONT:
		tmpCurPos, err := LocalMusicList[OTHERS_MUSIC_LIST].GetFirst()
		if nil != err {
			log.Println(log.ErrorLog, err.Error())
			return ACTION_NULL, err
		}
		LocalMusicList[OTHERS_MUSIC_LIST].SetCurPos(tmpCurPos)

		if LocalMusicList[OTHERS_MUSIC_LIST].GetCurPos().Value.(*SongInfo).CanPlay {

		} else {
			LocalMusicList[OTHERS_MUSIC_LIST].GetValidNext()
		}

		songId = LocalMusicList[OTHERS_MUSIC_LIST].GetCurPos().Value.(*SongInfo)
	case ACTION_NEXT_PAGE_REPLACE_LIST, ACTION_MISS_PAGE_REPLACE_LIST, ACTION_LAST_PAGE:
		var replace bool = true
		var pageSize MusicLenType = PAGE_SIZE
		if ACTION_NEXT_PAGE_REPLACE_LIST == action {
			// 还有剩余分页，拉取分页
			if val, err := NormalListMap[OTHERS_LIST_PAGE].GetLast(); nil == err {
				index = val.Value.(*PageNode).PageIndex * PAGE_SIZE
			}
		} else if ACTION_MISS_PAGE_REPLACE_LIST == action {
			// 有缺失的分页，拉取分页
			index = (NormalListMap[OTHERS_LIST_PAGE].GetMissPage() - 1) * PAGE_SIZE
		} else {
			NormalListMap[OTHERS_LIST_PAGE].Init()
			// 分页全部拉取完毕，重新拉取第一页
		}

		srcType := getMusicSrcType(PlayerType_Other)
		list, err := GetMusicListNew(PlayerType_Other, true, http.MusicListServerType{
			Src:     srcType,
			Id:      getServiceId(srcType),
			Params:  getServiceParams(srcType),
			Start:   index,
			Size:    pageSize,
			WantTts: true,

			Oftag:        NormalPlayerListSrc.TagName,
			OftagForShow: NormalPlayerListSrc.TagNameShow,
			Mode:         CurPlayingMode,
			CloudId:      NormalPlayerListSrc.CloudId,
			ModeId:       NormalPlayerListSrc.ModeId,
		})
		//list, err := getMusicList(PlayerType_Other, srcType, getServiceId(srcType),
		//	getServiceParams(srcType), index, pageSize, true, CurPlayingMode)
		if nil != err {
			log.Println(log.ErrorLog, err.Error())
			return ACTION_NULL, err
		}
		updateNormalPlayListAndPage(list, index, replace)

		songId, songUrl = getCanPlaySong(list)
	default:
		log.Println(log.DebugLog, "err action")
		return ACTION_NULL, Normal_ERR_ACTION
	}

	return action, lowLevelPlayApi(commonPlayApiArg{
		prepare:            prepare,
		songId:             songId,
		songUrl:            songUrl,
		tts:                tts,
		ttsUrl:             ttsUrl,
		ttsNow:             true,
		needChangeNHDIndex: false,
		srcType:            NormalPlayerListSrc.MusicSrc,
		rspId:              rspId,
	})
}

func getNextPrevActionByNormalPlayer(needNextAction bool) MusicChangeAction {
	defer func() {
		if playerRecoverLevel <= MIDDLE_RECOVER_LEVEL {
			if err := recover(); err != nil {
				log.Println(log.ErrorLog, err)
			}
		}
	}()

	if nil == LocalMusicList[OTHERS_MUSIC_LIST].GetCurPos() {
		return ACTION_NULL
	}

	if needNextAction {
		log.Println(log.DebugLog, "Next...")
	} else {
		log.Println(log.DebugLog, "Prev...")
	}
	var ret MusicChangeAction
	back, _ := NormalListMap[OTHERS_LIST_PAGE].GetLast()
	if needNextAction {
		if nil != LocalMusicList[OTHERS_MUSIC_LIST].GetValidFrontBackSong(false) &&
			LocalMusicList[OTHERS_MUSIC_LIST].GetCurPos().Value.(*SongInfo).Id != LocalMusicList[OTHERS_MUSIC_LIST].GetValidFrontBackSong(false).Id {
			ret = ACTION_PLAY_DIRECT
		} else if autoStopPlayWhenListPlayOnce {
			ret = ACTION_STOP_PLAYER
			autoStopPlayWhenListPlayOnce = false
		} else if NormalListMap[OTHERS_LIST_PAGE].HasMore {
			// 还有分页
			ret = ACTION_NEXT_PAGE_REPLACE_LIST
		} else if nil != back &&
			back.Value.(*PageNode).PageIndex != MusicLenType(NormalListMap[OTHERS_LIST_PAGE].List.Len()) {
			// 有缺失的分页，拉取分页
			ret = ACTION_MISS_PAGE_REPLACE_LIST
		} else {
			if 1 == MusicLenType(NormalListMap[OTHERS_LIST_PAGE].List.Len()) ||
				MUSIC_LIST_NULL == NormalPlayerListSrc.MusicSrc {
				//如果只有1页 / 如果都是单曲插入，直接播放第1首
				ret = ACTION_PLAY_FRONT
			} else {
				ret = ACTION_LAST_PAGE
			}
		}
	} else {
		if nil != LocalMusicList[OTHERS_MUSIC_LIST].GetValidFrontBackSong(true) &&
			LocalMusicList[OTHERS_MUSIC_LIST].GetCurPos().Value.(*SongInfo).Id != LocalMusicList[OTHERS_MUSIC_LIST].GetValidFrontBackSong(true).Id {
			ret = ACTION_PLAY_DIRECT
		} else if PRIVATE_FM == NormalPlayerListSrc.MusicSrc || MUSIC_SHARE_RCMD == NormalPlayerListSrc.MusicSrc {
			ret = ACTION_PLAY_BACK
		} else if NormalListMap[OTHERS_LIST_PAGE].HasMore {
			// 还有分页
			ret = ACTION_NEXT_PAGE_REPLACE_LIST
		} else if nil != back && back.Value.(*PageNode).PageIndex !=
			MusicLenType(NormalListMap[OTHERS_LIST_PAGE].List.Len()) {
			// 有缺失的分页，拉取分页
			ret = ACTION_MISS_PAGE_REPLACE_LIST
		} else {
			if 1 == MusicLenType(NormalListMap[OTHERS_LIST_PAGE].List.Len()) ||
				MUSIC_LIST_NULL == NormalPlayerListSrc.MusicSrc {
				// 如果只有1页 / 如果都是单曲插入，直接播放最后1首
				ret = ACTION_PLAY_BACK
			} else {
				ret = ACTION_LAST_PAGE
			}
		}
	}
	log.Println(log.DebugLog, "action:", ret, "   MusicSrc:", NormalPlayerListSrc.MusicSrc)
	return ret
}

func normalPlayerStHd(status PlayerDetail) error {
	defer func() {
		if playerRecoverLevel <= LOW_RECOVER_LEVEL {
			if err := recover(); err != nil {
				log.Println(log.ErrorLog, err)
			}
		}
	}()

	switch status.Status {
	case MUSIC_ST_PLAYING:
		if "" != status.Uuid {
			if normalNeedSeekToPos {
				normalNeedSeekToPos = false
				sendCurPlayerMusicCmd(CMD_PLAYER_SEEKTO, normalSeekPos)
			}

			updateNormalPlayerStatus(status)

			if ttsMusicUuid != status.Uuid {
				ttsNoMusic = false
			}
		}
	case MUSIC_ST_FOR_NEXT:
		_, err = normalNextApi(true, nil)
		if nil != err {
			log.Println(log.ErrorLog, err.Error())
		} else {
			log.Println(log.DebugLog, "prepare for next...")
		}
	case MUSIC_ST_COMPLETED:
		if ttsNoMusic {
			ttsNoMusic = false
			forcePausePlayer(PlayerType_Other)
			NoticePlayerSendSCmd(SCMD_SuperTask_Tts_Play, ttsInfo, CONST_AUDIO_ID, AdSrcType_TTS, TTS_LEVEL_1, true,
				false)
			log.Println(log.DebugLog, "tts when music end:", ttsInfo)
		}
		if "" != status.Uuid {
			updateNormalPlayerStatus(status)
		}
	case MUSIC_ST_PAUSED, MUSIC_ST_IDLE:
		if "" != status.Uuid {
			updateNormalPlayerStatus(status)
		}
	default:
		log.Printf(log.WarningLog, "invalid st:0x%x\n", status.Status)
	}

	return nil
}

func updateNormalPlayerStatus(status PlayerDetail) uint8 {
	defer func() {
		if playerRecoverLevel <= LOW_RECOVER_LEVEL {
			if err := recover(); err != nil {
				log.Println(log.ErrorLog, err)
			}
		}
	}()

	if status.Status < MUSIC_ST_MAX && status.Status >= MUSIC_ST_IDLE {
		normalPlayerSt.PlayerSrc = CurPlayerSrc
		// 连续任务状态
		normalPlayerSt.MusicId = &status.Uuid
		normalPlayerSt.ContinuousTaskSt = status.Status
		normalPlayerSt.CurPlayingPos = status.CurPos
		normalPlayerSt.MusicListId = PlayListSrcRec.MusicListId
		normalPlayerSt.Duration = status.Duration
		normalPlayerSt.ContinuousStChangeTime = time.Now()
		normalPlayerSt.Type = PlayListSrcRec.MusicSrc
		normalPlayerSt.TaskField = FIELD_MUSIC
	}

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

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

func normalListPlay(e interface{}) MusicAction {
	defer func() {
		if playerRecoverLevel <= MIDDLE_RECOVER_LEVEL {
			if err := recover(); err != nil {
				log.Println(log.ErrorLog, err)
			}
		}
	}()

	var srcType MusicSrcType
	var songList []SongInfo
	switch eVal := e.(type) {
	case *ServerMusicList:
		// 歌单
		srcType = eVal.MusicList.Type
		songList = eVal.MusicList.SongList
	case *ServerMusicLists:
		listIndex = 0 // 歌单记录索引清零
		// 歌单列表
		srcType = eVal.MusicLists[0].Type
		songList = eVal.MusicLists[0].SongList
	default:
		log.Println(log.ErrorLog, "err params when play music")
		return MUSIC_ERR_ACTION
	}
	// 检查歌单是否为空
	if nil == songList || len(songList) == 0 {
		log.Println(log.ErrorLog, "nil songlist from server")
		return MUSIC_ERR_ACTION
	}

	log.Println(log.DebugLog, "type:", srcType)

	normalListPlayExec(e)

	return MUSIC_LISTS_ACTION
}

/**
e 的格式为：*ServerMusicList 或者 *ServerMusicLists
*/
func normalListPlayExec(e interface{}) (MusicAction, error) {
	defer func() {
		if playerRecoverLevel <= MIDDLE_RECOVER_LEVEL {
			if err := recover(); err != nil {
				log.Println(log.ErrorLog, err)
			}
		}
	}()

	var songId *SongInfo = nil
	var songUrl *string = nil
	// 歌单id不同，或者更新时间变，或者当前播放列表空，需要替换歌单
	songId, songUrl = getCanPlaySong(e)

	// 更新页信息,且第一次推下来，肯定时第1页
	NormalListMap[OTHERS_LIST_PAGE].Init()

	updateNormalPlayListAndPage(e, 0, true)
	// 定位当前歌曲记录节点到播放歌曲位置
	if nil != songId {
		LocalMusicList[OTHERS_MUSIC_LIST].Search(songId, true)
	}
	// 更新当前播放列表来源信息
	updateNormalPlayListSrcRec(e)

	var tts, ttsUrl string = "", ""
	var rspId string = ""
	switch eVal := e.(type) {
	case *ServerMusicList:
		tts = eVal.InnerTts
		ttsUrl = eVal.InnerTtsUrl
		rspId = eVal.RspId
	case *ServerMusicLists:
		tts = eVal.InnerTts
		ttsUrl = eVal.InnerTtsUrl
		rspId = eVal.RspId
	default:

	}

	err = lowLevelPlayApi(commonPlayApiArg{
		prepare:            false,
		songId:             songId,
		songUrl:            songUrl,
		tts:                tts,
		ttsUrl:             ttsUrl,
		ttsNow:             true,
		needChangeNHDIndex: false,
		srcType:            NormalPlayerListSrc.MusicSrc,
		rspId:              rspId,
	})

	if err != nil {
		log.Println(log.ErrorLog, err.Error())
		return NORMAL_ERR_ACTION, err
	}

	return NORMAL_MORE_T1_UPDATE, nil
}

func updateNormalPlayListAndPage(e interface{}, index MusicLenType, replace bool) {
	defer func() {
		if playerRecoverLevel <= HIGH_RECOVER_LEVEL {
			if err := recover(); err != nil {
				log.Println(log.ErrorLog, err)
			}
		}
	}()

	var songs *[]SongInfo
	var lenType MusicLenType = 0
	var topIndex MusicLenType
	var hasMore bool = false // 查看歌曲是否还有更多

	switch eVal := e.(type) {
	case *ServerMusicList:
		songs = &(eVal.MusicList.SongList)
		lenType = MusicLenType(len(e.(*ServerMusicList).MusicList.SongList))
		topIndex = MusicLenType(eVal.MusicList.Index)
		hasMore = eVal.MusicList.HasMore

		log.Println(log.DebugLog, "Has more musics:", eVal.MusicList.HasMore)
	case *ServerMusicLists:
		songs = &(eVal.MusicLists[0].SongList)
		lenType = MusicLenType(len(e.(*ServerMusicLists).MusicLists[0].SongList))
		topIndex = MusicLenType(eVal.MusicLists[0].Index)
		hasMore = eVal.MusicLists[0].HasMore

		log.Println(log.DebugLog, "Has more musics:", eVal.MusicLists[0].HasMore)
		log.Println(log.DebugLog, "Has more Lists:", PlayListSrcRec.HasMore)
	default:
		log.Println(log.WarningLog, "err params")
		return
	}

	pageNode := GetPageFromIndex(index, PAGE_SIZE)
	err := NormalListMap[OTHERS_LIST_PAGE].Push(pageNode)
	if nil != err {
		log.Println(log.WarningLog, err.Error())
	}
	NormalListMap[OTHERS_LIST_PAGE].HasMore = hasMore
	if !hasMore {
		// 获取最大的页面值
		NormalListMap[OTHERS_LIST_PAGE].MaxPage = pageNode.PageIndex
		log.Println(log.DebugLog, "MaxPage:", pageNode.PageIndex)
	}

	if NormalListMap[OTHERS_LIST_PAGE].MaxPage == MusicLenType(NormalListMap[OTHERS_LIST_PAGE].List.Len()) {
		NormalListMap[OTHERS_LIST_PAGE].HasMore = false
		NormalListMap[OTHERS_LIST_PAGE].MaxPage = 0
		log.Println(log.DebugLog, "reset music hasMore")
	}

	if replace {
		log.Println(log.DebugLog, "replace list, lenType:", lenType, "  topIndex:", topIndex)
		// 更新播放列表信息
		LocalMusicList[OTHERS_MUSIC_LIST].ReplaceBySlice(songs, lenType, 0, topIndex)
	} else {
		var offset MusicLenType = GetPageIndexFromIndex(index, PAGE_SIZE)
		log.Println(log.DebugLog, "add list, lenType:", lenType, "  offset:", offset,
			"  topIndex:", topIndex)
		// 更新播放列表信息
		LocalMusicList[OTHERS_MUSIC_LIST].AddBySlice(songs, lenType, 0, topIndex)
	}
}

func updateNormalPlayListSrcRec(e interface{}) {
	defer func() {
		if playerRecoverLevel <= HIGH_RECOVER_LEVEL {
			if err := recover(); err != nil {
				log.Println(log.ErrorLog, err)
			}
		}
	}()

	NormalPlayerListSrc.HasInsert = false
	switch eVal := e.(type) {
	case *ServerMusicList:
		NormalPlayerListSrc.MusicListId = &(eVal.MusicList.Id)
		NormalPlayerListSrc.TagName = &(eVal.Oftag)
		NormalPlayerListSrc.TagNameShow = &eVal.OftagForShow
		NormalPlayerListSrc.UpdateTime = eVal.MusicList.UpdateTime

		if (USER_LISTS == NormalPlayerListSrc.MusicSrc || USER_LISTS_COLLECT == NormalPlayerListSrc.MusicSrc ||
			ALBUM_ARTIST_ID == NormalPlayerListSrc.MusicSrc || USER_LISTS_CREATE == NormalPlayerListSrc.MusicSrc ||
			MUSIC_LIST_WORD == NormalPlayerListSrc.MusicSrc || MUSIC_LIST_SERACH_WORD == NormalPlayerListSrc.MusicSrc) &&
			(NormalPlayerListSrc.HasMore || MUSIC_LIST_NULL == eVal.MusicList.Type) {
			//如果之前状态是歌单列表，且还有更多歌单，不要替换
		} else {
			NormalPlayerListSrc.MusicSrc = eVal.MusicList.Type
			// 推送下来的时一个歌单，没有歌单列表，因此需要清除歌单列表hasMore
			NormalPlayerListSrc.HasMore = false

			NormalPlayerListSrc.MusicListIdIndex = INVALID_MUSIC_LEN
			NormalPlayerListSrc.MusicListIds = nil
			NormalPlayerListSrc.MusicListIdsLen = INVALID_MUSIC_LEN
			NormalPlayerListSrc.MusicListMaxLen = INVALID_MUSIC_LEN
		}
	case *ServerMusicLists:
		NormalPlayerListSrc.MusicListId = &(eVal.MusicLists[0].Id)
		NormalPlayerListSrc.TagName = &(eVal.Oftag)
		NormalPlayerListSrc.TagNameShow = &eVal.OftagForShow
		NormalPlayerListSrc.MusicListIdIndex = 0
		if playUserLists {
			// 如果当前播放的是我的歌单
			NormalPlayerListSrc.MusicSrc = USER_LISTS
		} else {
			NormalPlayerListSrc.MusicSrc = eVal.MusicLists[0].Type
		}
		NormalPlayerListSrc.UpdateTime = e.(*ServerMusicLists).MusicLists[0].UpdateTime
		NormalPlayerListSrc.HasMore = e.(*ServerMusicLists).HasMore

		NormalPlayerListSrc.MusicListIdsLen = MusicLenType(len(eVal.MusicLists))
		var listIds []ListIds = make([]ListIds, NormalPlayerListSrc.MusicListIdsLen)
		for k, v := range eVal.MusicLists {
			listIds[k].Id = &(eVal.MusicLists[k].Id)
			listIds[k].UpdateTime = v.UpdateTime
		}
		NormalPlayerListSrc.MusicListIds = &listIds

		log.Println(log.DebugLog, "MusicListIdIndex: ", NormalPlayerListSrc.MusicListIdIndex,
			" NormalPlayerListSrc.MusicListIdsLen:", NormalPlayerListSrc.MusicListIdsLen)
		for k, v := range *NormalPlayerListSrc.MusicListIds {
			log.Println(log.DebugLog, k, ": ", *v.Id, " updateTime:", v.UpdateTime)
		}

		listIndex += NormalPlayerListSrc.MusicListIdsLen

		if NormalPlayerListSrc.HasMore {
			NormalPlayerListSrc.MusicListMaxLen = listIndex
		}
	default:
		log.Println(log.WarningLog, "err params")
	}
	log.Println(log.DebugLog, "MusicListId:", *NormalPlayerListSrc.MusicListId, "  MusicListIdIndex:",
		NormalPlayerListSrc.MusicListIdIndex,
		"  MusicSrc:", NormalPlayerListSrc.MusicSrc, "  UpdateTime:", NormalPlayerListSrc.UpdateTime)
}

/* 会对歌单进行鉴权保护　*/
func lowLevelPlayApi(arg commonPlayApiArg) error {
	defer func() {
		if playerRecoverLevel <= HIGH_RECOVER_LEVEL {
			if err := recover(); err != nil {
				log.Println(log.ErrorLog, err)
			}
		}

		if needForcePauseNormalPlayer {
			forcePauseNormalPlayer()
		}
	}()
	needForcePauseNormalPlayer = false

	var tts *string = nil
	var ttsAdSrcType AdSrcType
	if len(arg.ttsUrl) > 0 {
		tts = &arg.ttsUrl
		ttsAdSrcType = AdSrcType_FILE_MIX
	} else if len(arg.tts) > 0 {
		tts = &arg.tts
		ttsAdSrcType = AdSrcType_TTS_MIX
	}

	var musicCnt MusicLenType = 0
	var pageCnt MusicLenType = 0
	var needComfirm bool = false
	var songDetail *ServerSongDetail = nil
	var err error
	if nil == arg.songUrl || len(*arg.songUrl) == 0 {
	searchMusic:
		if nil != arg.songId && len(arg.songId.Id) > 0 {
			songDetail, err = getSongDetailInfo(PlayerType_Other, &arg.songId.Id, arg.ttsNow)
			if nil != err {
				log.Println(log.ErrorLog, err.Error())
				if Server_ERR_RET == err {
					needForcePauseNormalPlayer = true
					return err
				}
				if SINGLE_SONG == arg.srcType {
					// 如果是单曲，服务端需要保证该单曲是可以播放的，因此不会进入该分之，如果进入，拉取下一首播放
				}
				needComfirm = true
			} else if "" == songDetail.Song.Url {
				needComfirm = true
			} else {
				needComfirm = false
				arg.songUrl = &songDetail.Song.Url
			}
		} else {

			needComfirm = true
		}
		if needComfirm {
			// 播放失败，需要做拉取并鉴权处理
			found, step := LocalMusicList[OTHERS_MUSIC_LIST].GetValidNext()
			log.Println(log.DebugLog, "found:", found, " step:", step)
			if !found || musicCnt >= MusicLenType(LocalMusicList[OTHERS_MUSIC_LIST].List.Len()) {
			searchPage:
				// case 1: 歌单中还有分页需要处理
				if NormalListMap[OTHERS_LIST_PAGE].HasMore ||
					pageCnt < NormalListMap[OTHERS_LIST_PAGE].MaxPage {
					log.Printf(log.DebugLog, "\nhas page need to pull.%d\n", arg.srcType)
					// 还有分页
					arg.songId, err = hasPageNeedComfirmByNormal()
					pageCnt++
					if nil != err {
						goto searchPage
					} else {
						musicCnt = 0
						goto searchMusic
					}
				}
				// case 2:　错误信息播报
				log.Printf(log.DebugLog, "\n can not play because of lists is invalid:%v srcType:%d\n",
					MusicErrTtsMap[string(arg.srcType)], arg.srcType)

				forcePauseNormalPlayer()

				NoticePlayerSendSCmd(SCMD_SuperTask_Tts_Play, MusicErrTtsMap[string(arg.srcType)], CONST_AUDIO_ID, AdSrcType_TTS,
					TTS_LEVEL_1, true, false)

				return MusicList_ERR_MUSIC_NULL

			} else {
				musicCnt += step
				arg.songId = LocalMusicList[OTHERS_MUSIC_LIST].GetCurPos().Value.(*SongInfo)
				goto searchMusic
			}
		}
	}
	if arg.prepare {
		sendCurPlayerMusicCmd(CMD_PLAYER_PERPARE_NEXT, &arg.songId.Id, arg.songUrl, tts, ttsAdSrcType,
			arg.songId.Duration, arg.songId.Gain, arg.songId.BGUrl)
	} else {
		sendCurPlayerMusicCmd(CMD_PLAYER_PLAY, &arg.songId.Id, arg.songUrl, tts, ttsAdSrcType,
			arg.songId.Duration, arg.songId.Gain, arg.songId.BGUrl)
	}
	LocalMusicList[PLAYSONG_MUSIC_LIST].Push(arg.songId, true)

	if nil == songDetail {
		songDetail, err = getSongDetailInfo(PlayerType(hdCur.GetPlayerHd().GetPlayerId()), &arg.songId.Id, arg.ttsNow)
		if nil != err {
			log.Println(log.ErrorLog, err.Error())
			return err
		}
		fmt.Printf("songDetail:%v\n", songDetail)
	}
	LocalMusicList[OTHERS_MUSIC_LIST].GetCurPos().Value.(*SongInfo).IsLiked = songDetail.Song.IsLiked
	// not change icon
	//if songDetail.Song.IsLiked {
	//	vui.IconLed_iconMusic003.Show();
	//} else {
	//	vui.IconLed_iconMusic001.Show();
	//}

	return nil
}

// 鉴权时，处理还有分页待拉取的情况
func hasPageNeedComfirmByNormal() (songId *SongInfo, err error) {
	defer func() {
		if playerRecoverLevel <= LOW_RECOVER_LEVEL {
			if err := recover(); err != nil {
				log.Println(log.ErrorLog, err)
			}
		}
	}()

	var index MusicLenType = 0
	var pageSize MusicLenType = PAGE_SIZE
	var replace bool = true
	if NormalListMap[OTHERS_LIST_PAGE].HasMore {
		// 还有分页
		if val, err := NormalListMap[OTHERS_LIST_PAGE].GetLast(); nil == err {
			index = val.Value.(*PageNode).PageIndex * PAGE_SIZE
		}
	} else {
		// 从第１页开始拉取
		NormalListMap[OTHERS_LIST_PAGE].Init()
	}
	srcType := getMusicSrcType(PlayerType_Other)
	list, err := GetMusicListNew(PlayerType_Other, true, http.MusicListServerType{
		Src:     srcType,
		Id:      getServiceId(srcType),
		Params:  getServiceParams(srcType),
		Start:   index,
		Size:    pageSize,
		WantTts: true,

		Oftag:        NormalPlayerListSrc.TagName,
		OftagForShow: NormalPlayerListSrc.TagNameShow,
		Mode:         CurPlayingMode,
		CloudId:      NormalPlayerListSrc.CloudId,
		ModeId:       NormalPlayerListSrc.ModeId,
	})
	//list, err := getMusicList(PlayerType_Other, srcType, getServiceId(srcType), getServiceParams(srcType),
	//	index, pageSize, true, CurPlayingMode)
	if nil != err {
		log.Println(log.ErrorLog, err.Error())
		return nil, err
	}
	updateNormalPlayListAndPage(list, index, replace)

	if nil != LocalMusicList[OTHERS_MUSIC_LIST].GetCurPos() {
		return LocalMusicList[OTHERS_MUSIC_LIST].GetCurPos().Value.(*SongInfo), nil
	} else {
		return nil, MusicList_ERR_MUSIC_NULL
	}
}

func forcePauseNormalPlayer() {
	if MUSIC_ST_PAUSED != PlayerHander[PlayerType_Other].GetPlayerStatus().Status &&
		MUSIC_ST_IDLE != PlayerHander[PlayerType_Other].GetPlayerStatus().Status {
		wifiPauseApi()
		status := PlayerHander[PlayerType_Other].GetPlayerStatus()
		status.Status = MUSIC_ST_PAUSED
		status.CurPos = 0
		log.Println(log.DebugLog, "forcePauseNormalPlayer set CurPos to 0")
		PlayerHander[PlayerType_Other].SetPlayerStatus(status)
	}
}
