package http

import (
	. "netease_control_center/globals"
	"netease_control_center/interfaces/log"
	"time"
)

func init() {
	// songPlayInfo
	RegisteApi(reqSongPlayInfo{}, ApiContainer{Url: URL_MUSIC_VBOX + BODY_MUSIC_PLAYINFO, ReqparamIsString: true, IsEncrypted: true})
	// songDetail
	RegisteApi(reqMusicInfo{}, ApiContainer{Url: URL_MUSIC_VBOX + BODY_MUSIC_DETAIL, ReqparamIsString: true, IsEncrypted: true})
	// list
	RegisteApi(reqRedFm{}, ApiContainer{Url: URL_MUSIC_VBOX + BODY_RED_FM, ReqparamIsString: true, IsEncrypted: true})
	RegisteApi(reqListId{}, ApiContainer{Url: URL_MUSIC_VBOX + BODY_LIST_BY_ID, ReqparamIsString: true, IsEncrypted: true})
	RegisteApi(reqPrivateFM{}, ApiContainer{Url: URL_MUSIC_VBOX + BODY_FM_PRIVATE, ReqparamIsString: true, IsEncrypted: false})
	RegisteApi(reqAlbumByID{}, ApiContainer{Url: URL_MUSIC_VBOX + BODY_ALBUM_BYID, ReqparamIsString: true, IsEncrypted: true})
	RegisteApi(reqArtist{}, ApiContainer{Url: URL_MUSIC_VBOX + BODY_ARTIST, ReqparamIsString: true, IsEncrypted: true})

	RegisteApi(reqNewTopList{}, ApiContainer{Url: URL_MUSIC_VBOX + BODY_NEW_TOPLIST, ReqparamIsString: true, IsEncrypted: true})
	RegisteApi(reqHotTopList{}, ApiContainer{Url: URL_MUSIC_VBOX + BODY_HOT_TOLIST, ReqparamIsString: true, IsEncrypted: true})
	RegisteApi(reqDailyPush{}, ApiContainer{Url: URL_MUSIC_VBOX + BODY_DAILY_PUSH, ReqparamIsString: true, IsEncrypted: true})
	RegisteApi(reqDenonTopList{}, ApiContainer{Url: URL_MUSIC_VBOX + BODY_DENON_TOPLIST, ReqparamIsString: true, IsEncrypted: true})
	RegisteApi(reqClassicTopList{}, ApiContainer{Url: URL_MUSIC_VBOX + BODY_CLASSIC_TOPLIST, ReqparamIsString: true, IsEncrypted: true})
	RegisteApi(reqBeatPortTopList{}, ApiContainer{Url: URL_MUSIC_VBOX + BODY_BEATPORT_TOPLIST, ReqparamIsString: true, IsEncrypted: true})
	RegisteApi(reqOriginalTopList{}, ApiContainer{Url: URL_MUSIC_VBOX + BODY_ORIGINAL_TOPLIST, ReqparamIsString: true, IsEncrypted: true})
	RegisteApi(reqSorignTopList{}, ApiContainer{Url: URL_MUSIC_VBOX + BODY_SORIGN_TOPLIST, ReqparamIsString: true, IsEncrypted: true})

	RegisteApi(reqTopList{}, ApiContainer{Url: URL_MUSIC_VBOX + BODY_TOPLIST_COMMON, ReqparamIsString: true, IsEncrypted: true})

	RegisteApi(reqNewList{}, ApiContainer{Url: URL_MUSIC_VBOX + BODY_NEWLIST_COMMON, ReqparamIsString: true, IsEncrypted: true})

	RegisteApi(reqServerRcmd{}, ApiContainer{Url: URL_MUSIC_VBOX + BODY_Server_Rcmd, ReqparamIsString: true, IsEncrypted: true})

	RegisteApi(reqSongSimilarList{}, ApiContainer{Url: URL_MUSIC_VBOX + BODY_SONG_SIMILAR, ReqparamIsString: true, IsEncrypted: false})

	RegisteApi(reqMusicShareRcmd{}, ApiContainer{Url: URL_Music_Share_Rcmd, ReqparamIsString: true, IsEncrypted: true})
	RegisteApi(reqMusicSpecialRcmd{}, ApiContainer{Url: URL_Music_Special_Rcmd, ReqparamIsString: true, IsEncrypted: true})
	// lists
	RegisteApi(reqCreateLists{}, ApiContainer{Url: URL_MUSIC_VBOX + BODY_CREATE_LIST, ReqparamIsString: true, IsEncrypted: true})
	RegisteApi(reqCollectLists{}, ApiContainer{Url: URL_MUSIC_VBOX + BODY_COLLECT_LIST, ReqparamIsString: true, IsEncrypted: true})
	RegisteApi(reqAlbumByArtist{}, ApiContainer{Url: URL_MUSIC_VBOX + BODY_ALBUM_BYARTIST, ReqparamIsString: true, IsEncrypted: true})
	RegisteApi(reqByExtraData(""), ApiContainer{Url: URL_MUSIC_VBOX + BODY_EXTRADATA_LIST, ReqparamIsString: false, IsEncrypted: false})
	RegisteApi(reqWordLists{}, ApiContainer{Url: URL_MUSIC_VBOX + BODY_WORD_LIST, ReqparamIsString: true, IsEncrypted: true})
	RegisteApi(reqSearchWordLists{}, ApiContainer{Url: URL_MUSIC_VBOX + BODY_SEARCH_WORD_LIST, ReqparamIsString: true, IsEncrypted: true})

	RegisteApi(reqBirthdayInfo{}, ApiContainer{Url: URL_BIRTHDAY_INFO, ReqparamIsString: true, IsEncrypted: true})

	RegisteApi(reqCommonGetPlayListRcmd{}, ApiContainer{Url: URL_Common_GetPlaylist_Rcmd, ReqparamIsString: true, IsEncrypted: true})
	RegisteApi(reqGetNextSongRcmd{}, ApiContainer{Url: URL_Next_Song_Get_Rcmd, ReqparamIsString: true, IsEncrypted: true})
	RegisteApi(reqRadioDetailInfo{}, ApiContainer{Url: URL_Radio_Detail_Rcmd, ReqparamIsString: true, IsEncrypted: true})
	RegisteApi(reqGetRadioPlayListRcmd{}, ApiContainer{Url: URL_Get_Radio_List_Rcmd, ReqparamIsString: true, IsEncrypted: true})

	RegisteApi(reqGetMusicPlayListInfoRcmd{}, ApiContainer{Url: URL_Get_Music_Play_List_Rcmd, ReqparamIsString: true, IsEncrypted: true})
	RegisteApi(reqGetRadioPlayListInfoRcmd{}, ApiContainer{Url: URL_Get_Radio_Play_List_Rcmd, ReqparamIsString: true, IsEncrypted: true})
}

func GetSongPlayInfoDo(id *string) (*ServerSongPlay, int, *string, error) {
	if nil == id {
		return nil, 0, nil, Server_ERR_RET
	}
	var reqbody reqSongPlayInfo = reqSongPlayInfo{SongId: *id}
	var res ServerSongPlay
	code, detail, err := postInterface(reqbody, &res)
	if int(ERR_SUCCESS) != code && "" != detail {
		return nil, code, &detail, Server_ERR_RET
	}
	if nil != err {
		log.Println(log.ErrorLog, err.Error())
		return nil, code, nil, err
	}
	return &res, code, nil, nil
}

func GetSongDetailInfoDo(id *string) (*ServerSongDetail, int, *string, error) {
	if nil == id {
		return nil, 0, nil, Server_ERR_RET
	}

	var reqbody interface{}
	if PlayListSrcRec.BizType == BIZ_TYPE_MUSIC {
		reqbody = reqMusicInfo{SongId: *id}
	} else {
		var albumId string
		if song, err := GetCurWifiSongInfo(); nil == err {
			albumId = song.AlbumId
		}
		reqbody = reqRadioDetailInfo{SongId: *id, AlbumId: albumId, BizType: PlayListSrcRec.BizType, ExtraData: PlayListSrcRec.ExtraData}
	}

	var res ServerSongDetail
	code, detail, err := postInterface(reqbody, &res)

	if int(ERR_SUCCESS) != code && "" != detail {
		return nil, code, &detail, Server_ERR_RET
	}
	if nil != err {
		log.Println(log.ErrorLog, err.Error())
		return nil, code, nil, err
	}
	return &res, code, nil, nil
}

func GetMusicPlayListInfoDo(listinfo PlayListServerType) (*MusicPlayListInfo, int, *string, error) {
	if nil == listinfo.Id {
		return nil, 0, nil, Server_ERR_RET
	}

	var reqbody interface{}

	reqbody = reqGetMusicPlayListInfoRcmd{PlaylistId: *listinfo.Id, ModeId: listinfo.ModeId}

	var res MusicPlayListInfo
	code, detail, err := postInterface(reqbody, &res)

	if int(ERR_SUCCESS) != code && "" != detail {
		return nil, code, &detail, Server_ERR_RET
	}
	if nil != err {
		log.Println(log.ErrorLog, err.Error())
		return nil, code, nil, err
	}
	return &res, code, nil, nil
}

func GetRadioPlayListInfoDo(listinfo PlayListServerType) (*RadioPlayListInfo, int, *string, error) {
	if nil == listinfo.Id {
		return nil, 0, nil, Server_ERR_RET
	}

	var reqbody interface{}

	reqbody = reqGetRadioPlayListInfoRcmd{RadioId: *listinfo.Id, ModeId: listinfo.ModeId}

	var res RadioPlayListInfo
	code, detail, err := postInterface(reqbody, &res)

	if int(ERR_SUCCESS) != code && "" != detail {
		return nil, code, &detail, Server_ERR_RET
	}
	if nil != err {
		log.Println(log.ErrorLog, err.Error())
		return nil, code, nil, err
	}
	return &res, code, nil, nil
}

func GetMusicListDoNew(musicList MusicListServerType) (*ServerMusicList, int, *string, error) {
	var res ServerMusicList
	var code int
	var detail string
	var err error

	if musicList.TrigServer {
		if int(PlayerType_Wifi) == musicList.Source {
			if musicList.Src == NATURAL_SOUND_LIST {
				var req reqGetNextSongRcmd
				if musicList.Id == nil {
					req = reqGetNextSongRcmd{ExtraData: musicList.ExtraData}
				} else {
					req = reqGetNextSongRcmd{SongId: *musicList.Id, ExtraData: musicList.ExtraData}
				}
				code, detail, err = postInterface(req, &res)
			}
		} else if int(PlayerType_Dlna) == musicList.Source {
			var req reqGetNextSongRcmd
			req = reqGetNextSongRcmd{ExtraData: musicList.ExtraData, PlaySource:musicList.Source, Cmd:musicList.Cmd}
			code, detail, err = postInterface(req, &res)
		}
	} else {
		switch musicList.Src {
		case SERVER_RCMD:
			req := reqServerRcmd{PlayMode: musicList.Mode, WantTts: musicList.WantTts}
			code, detail, err = postInterface(req, &res)
		case SIMILAR_SONG:
			req := reqSongSimilarList{Size: musicList.Size, SongId: *musicList.Id, ModeId: musicList.ModeId}
			code, detail, err = postInterface(req, &res)
			res.ExtraData = musicList.ExtraData
		case MUSIC_SPECIAL_RCMD:
			log.Println(log.WarningLog, "Get special music from server...")
			req := reqMusicSpecialRcmd{Type: musicList.Src, PlayMode: musicList.Mode}
			code, detail, err = postInterface(req, &res)
		default:
			if musicList.Src > MUSIC_COMMON_TYPE_LIST && musicList.Src < RADIO_COMMON_TYPE_LIST {
				log.Println(log.WarningLog, "Get common play list from server, type Id: ", musicList.Src)
				var req reqCommonGetPlayListRcmd
				if musicList.Id == nil {
					req = reqCommonGetPlayListRcmd{Type: musicList.Src, Size: musicList.Size,
						Start: musicList.Start, ModeId: musicList.ModeId, PlayMode: musicList.Mode}
				} else {
					req = reqCommonGetPlayListRcmd{Type: musicList.Src, Id: *musicList.Id, Size: musicList.Size,
						Start: musicList.Start, ModeId: musicList.ModeId, PlayMode: musicList.Mode}
				}
				code, detail, err = postInterface(req, &res)
			} else if musicList.Src > RADIO_COMMON_TYPE_LIST {
				log.Println(log.WarningLog, "Get radio play list from server, type Id: ", musicList.Src)
				var req reqGetRadioPlayListRcmd
				if musicList.Id == nil {
					req = reqGetRadioPlayListRcmd{AlbumId: musicList.AlbumID, BizType: musicList.BizType, Offset: musicList.Start, Limit: musicList.Size, Order: musicList.Order, ExtraData: musicList.ExtraData}
				} else {
					req = reqGetRadioPlayListRcmd{SongId: *musicList.Id, AlbumId: musicList.AlbumID, BizType: musicList.BizType, Offset: musicList.Start, Limit: musicList.Size, Order: musicList.Order, ExtraData: musicList.ExtraData}
				}
				code, detail, err = postInterface(req, &res)
			} else {
				return getMusicListDo(musicList.Src, musicList.Id, musicList.Params, musicList.Start, musicList.Size,
					musicList.Mode, musicList.ExtraData)
			}
		}
	}

	if int(ERR_SUCCESS) != code && "" != detail {
		return nil, code, &detail, Server_ERR_RET
	}

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

	serverListProcess(&res, musicList)

	return &res, code, nil, nil
}

func getMusicListDo(src MusicSrcType, id *string, params *string, start MusicLenType, size MusicLenType, mode MusicPlayMode, extraData string) (*ServerMusicList, int, *string, error) {
	var res ServerMusicList
	var code int
	var detail string
	var err error
	switch src {
	case OTHERS:
		req := reqByExtraData(extraData)
		code, detail, err = postInterface(req, &res)
	case MUSIC_LIST_ID, MUSIC_LIST:
		req := reqListId{PlayListId: *id, Size: size, Start: start, PlayMode: mode}
		code, detail, err = postInterface(req, &res)
	case ALBUM_ID:
		req := reqAlbumByID{AlbumId: *id, PlayMode: mode, Start: start, Size: size}
		code, detail, err = postInterface(req, &res)
	case ARTIST_ID:
		req := reqArtist{Artist: *id, PlayMode: mode, Start: start, Size: size}
		code, detail, err = postInterface(req, &res)
	case PRIVATE_FM:
		log.Println(log.WarningLog, "Get private fm from server...")
		req := reqPrivateFM{Size: size, PlayMode: mode}
		code, detail, err = postInterface(req, &res)
	case MUSIC_SHARE_RCMD:
		req := reqMusicShareRcmd{}
		code, detail, err = postInterface(req, &res)
	case RED_FM:
		req := reqRedFm{Size: size, Start: start, PlayMode: mode}
		code, detail, err = postInterface(req, &res)
	case DAILY_PUSH:
		req := reqDailyPush{Size: size, PlayMode: mode}
		code, detail, err = postInterface(req, &res)
	case NEW_TOPLIST, HOT_TOPLIST, DENON_TOPLIST, CLASSIC_TOPLIST, BEATPORT_TOPLIST,
		ORIGINAL_TOPLIST, SORIGN_TOPLIST, ACG_TOPLIST, US_BILLBOARD_TOPLIST, JP_ORICON_TOPLIST,
		CH_NEW_TOPLIST, CH_HOT_TOPLIST:
		req := reqTopList{Size: size, TopListId: *id, Start: start, PlayMode: mode}
		code, detail, err = postInterface(req, &res)
	case JP_NEW_LIST, KOREA_NEW_LIST, EU_US_NEW_LIST:
		req := reqNewList{Size: size, NewListId: *id, Start: start, PlayMode: mode}
		code, detail, err = postInterface(req, &res)
	default:
		log.Println(log.DebugLog, Normal_ERR_ACTION.Error(), ":", src)
		return nil, code, nil, Normal_ERR_ACTION
	}

	if int(ERR_SUCCESS) != code && "" != detail {
		return nil, code, &detail, Server_ERR_RET
	}

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

	return &res, code, nil, nil
}

func GetMusicListsDoNew(musicList MusicListServerType) (*ServerMusicLists, int, *string, error) {
	var res ServerMusicLists
	var code int
	var detail string
	var err error
	switch musicList.Src {

	default:
		return getMusicListsDo(musicList.Src, musicList.Id, musicList.Params, musicList.Start, musicList.Size,
			musicList.Mode, musicList.ExtraData)
	}

	if int(ERR_SUCCESS) != code && "" != detail {
		return nil, code, &detail, Server_ERR_RET
	}

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

	serverListProcess(&res, musicList)

	return &res, code, nil, nil
}

func getMusicListsDo(src MusicSrcType, id *string, params *string, start MusicLenType, size MusicLenType, mode MusicPlayMode, extraData string) (*ServerMusicLists, int, *string, error) {
	var res ServerMusicLists
	var code int
	var detail string
	var err error
	switch src {
	case ALBUM_ARTIST_ID:
		req := reqAlbumByArtist{Artist: *id, Start: start, Size: size, PlayMode: mode}
		code, detail, err = postInterface(req, &res)
	case USER_LISTS_COLLECT:
		req := reqCollectLists{Start: start, Size: size}
		code, detail, err = postInterface(req, &res)
	case USER_LISTS_CREATE:
		req := reqCreateLists{Start: start, Size: size}
		code, detail, err = postInterface(req, &res)
	case MUSIC_LIST_WORD:
		req := reqWordLists{TagName: *id, Order: *params, Start: start, Size: size, PlayMode: mode}
		code, detail, err = postInterface(req, &res)
	case MUSIC_LIST_SERACH_WORD:
		req := reqSearchWordLists{TagName: *id, Start: start, Size: size, PlayMode: mode}
		code, detail, err = postInterface(req, &res)
	default:
		log.Println(log.DebugLog, Normal_ERR_ACTION.Error())
		return nil, code, nil, Normal_ERR_ACTION
	}
	log.Println(log.DebugLog, "get Music lists from server by src:", src)

	if int(ERR_SUCCESS) != code && "" != detail {
		return nil, code, &detail, Server_ERR_RET
	}

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

	return &res, code, nil, nil
}

func GetBirthdayInfo() (*BirthdayInfo, int, *string, error) {
	var req reqBirthdayInfo
	var res BirthdayInfo
	var detail string
	var code int
	var err error
	code, detail, err = postInterface(req, &res)

	if int(ERR_SUCCESS) != code && "" == detail {
		return nil, code, &detail, Server_ERR_RET
	}
	if nil != err {
		log.Println(log.ErrorLog, err.Error())
		return nil, code, nil, err
	}
	return &res, code, nil, nil
}

func postInterface(reqbody interface{}, resDetail interface{}) (code int, detail string, err error) {
	cnt := 0
	for cnt < MUSIC_POST_TRY_MAX {
		code, detail, err = HttpPostAuto(reqbody, resDetail)
		if err != nil {
			if Net_ERR_Post == err {
				time.Sleep(100 * time.Millisecond)
				cnt++
				log.Println(log.DebugLog, "post err,try ", cnt)
				continue
			} else {
				break
			}
		}
		break
	}
	return code, detail, err
}

func serverListProcess(serverList interface{}, reqParams MusicListServerType) {
	switch eval := serverList.(type) {
	case *ServerMusicList:
		if nil != reqParams.Oftag {
			eval.Oftag = *reqParams.Oftag
		}
		if nil != reqParams.OftagForShow {
			eval.OftagForShow = *reqParams.OftagForShow
		}

		eval.PlayMode = reqParams.Mode
		eval.CloudId = reqParams.CloudId
		eval.ModeId = reqParams.ModeId
	case *ServerMusicLists:
		if nil != reqParams.Oftag {
			eval.Oftag = *reqParams.Oftag
		}
		if nil != reqParams.OftagForShow {
			eval.OftagForShow = *reqParams.OftagForShow
		}

		eval.PlayMode = reqParams.Mode
		eval.CloudId = reqParams.CloudId
		eval.ModeId = reqParams.ModeId
	default:
		log.Printf(log.ErrorLog, "err type:%+v\n", serverList)
	}
}
