package globals

import (
	"container/list"
	"sync"
	"time"
)

type MusicLenType uint16 // 歌单、歌曲、分页长度类型

// 榜单、每日推荐歌单存储信息
type MusicSrcTypeRecInfo struct {
	MusicListIndex     MusicLenType // 对应歌单的播放位置,从0开始
	MusicListTimeStamp uint64
}

// 单首歌曲数据结构
type RawSong struct {
	Url  string
	Uuid string
}

//记录播放器音乐播放的实时状态， 也是发送给app的数据结构
type PlayerStatus struct {
	PlayerSrc PlayerSrcType `json:"playerSrc"` // 播放器的播放源
	// 连续播放任务变量
	MusicId                *string        `json:"songId"`   // 歌曲id
	MusicListId            *string        `json:"listId"`   // 歌单id
	ContinuousTaskSt       PlayerStatuses `json:"status"`   // 当前音乐播放状态（不包含提示音和tts的状态）
	ContinuousStChangeTime time.Time      `json:"-"`        // 状态发生变化的时间
	CurPlayingPos          uint32         `json:"pos"`      // 当前播放位置，单位ms
	Duration               uint32         `json:"duration"` // 歌曲总时长, 单位ms
	Type                   MusicSrcType   `json:"type"`
	TaskField              TaskFieldType  `json:"field"`
	// 单次播放任务变量
	SingleTaskSt       PlayerStatuses `json:"singleTaskSt"` // 单次播放任务状态
	SingleStChangeTime time.Time      `json:"-"`
}
type VboxStatus struct {
	PlayerStatus
	VolumePer   uint8         `json:"volPer"` // 音量传输百分比
	VolumeScale uint8         `json:"volScale"`
	Mute        bool          `json:"mute"`
	PlayMode    MusicPlayMode `json:"playmode"`
	Page        MusicLenType  `json:"page"`
	PageSize    MusicLenType  `json:"pageSize,omitempty"`
}

// 与app通信的数据结构
type AppParamBase struct {
	CmdId   Cmd    `json:"cmd"`
	MsgId   string `json:"msgid"`
	ReplyId string `json:"replyid"`
	Detail  string `json:"detail"`
	HasMore bool   `json:"hasMore"`
}

type AppPlayReq struct {
	Id           string       `json:"id"`
	Index        MusicLenType `json:"index"`
	Type         MusicSrcType `json:"type,omitempty"`
	ListId       string       `json:"listId"`
	Oftag        string       `json:"oftag"`
	OftagForShow string       `json:"showTag"`
	Field        MusicFieldSt `json:"field"`

	Action    string `json:"-"`
	ActionSrc string `json:"-"`
	ServerCmd uint16 `json:"-"`
}

type ListIds struct {
	Id         *string
	UpdateTime uint64
}

// 当前播放列表歌单来源信息
type PlayListSrcInfo struct {
	MusicListId      *string // 歌单ID
	TagName          *string // 歌单分类词
	ArtistId         *string
	TagNameShow      *string      // 分类次，app显示用
	MusicListIdIndex MusicLenType // 如果服务器下发了一个歌单列表，MusicListIdIndex表示MusicListId在歌单列表中的索引，如果没有列表，该值为0xffff
	MusicSrc         MusicSrcType // 歌曲来源信息类型
	CloudId          string
	ModeId           int64
	UpdateTime       uint64 // 歌单更新时间

	HasMore   bool // 是否还有歌单
	HasInsert bool // 是否有单曲插入过

	MusicListIds    *[]ListIds   // 服务器下发的歌单列表，如果没有，为nil
	MusicListIdsLen MusicLenType // 如果MusicListIds不为nil，该字段为其长度
	MusicListMaxLen MusicLenType // 歌单的最大数量

	CopyrightTts CopyrightPullTts

	ExtraData string

	BizType BizTypeDef
	Order   MusicLenType
	ListHasEnd bool //顺序播放的时候，是否播放完成
}

// 本地存储播放列表的数据结构
type MusicList struct {
	List        *list.List    // 双链表指针
	CurPosMusic *list.Element // 存储播放列表中当前的位置，历史列表时，该字段未使用
	ListType    MusicListType // 歌曲列表的类型
	lock        sync.RWMutex  // 读写锁
}

// 页面存储的列表
type NormalList struct {
	List      *list.List
	CurPos    *list.Element // 当前的节点，不一定是页面最大的节点
	HasMore   bool
	MaxPage   MusicLenType // 最大页数
	BackIndex MusicLenType
	lock      sync.RWMutex

	ListType NormalListIndexType // 扩展用，后续如果有与页面类似的列表结构，可以公用
}
type PageNode struct {
	PageIndex MusicLenType
}

// tts播放资源队列
type TtsList struct {
	List   *list.List
	CurPos *list.Element
	lock   sync.RWMutex
}

type TtsListCallback func(interface{})

// tts存储内容, 新建实例对象时，需要将callback置为nil
type TtsInfo struct {
	Tts         *string
	Uuid        *string
	SrcType     AdSrcType
	Level       TtsLevel
	NeedRepeat  bool
	Keep        bool
	Callback    TtsListCallback
	CbInterface interface{}
}

// 记录每日推荐歌曲是否播放过
type DailyPushRec struct {
	HasPlayed  bool      // 每日歌曲推荐是否播放过
	PlayedTime time.Time // 播放的时间
}

type ServerPullTts struct {
	PullTts    string `json:"pullTts"`
	PullTtsUrl string `json:"pullTtsUrl"`
	ErrTts     string `json:"errorTts"`
}

type CopyrightPullTts struct {
	Remark  string       `json:"remark"`
	Tts     string       `json:"tts"`
	TtsType MusicLenType `json:"type"`
}

// 版权问题tts type
const (
	TTS_TYPE_NULL MusicLenType = iota // 无tts
	TTS_TYPE_TEXT                     // tts是文本
	TTS_TYPE_URL                      // tts是url
)

// 歌单来源source，1：创建的 2：收藏的
const (
	LIST_SOURCE_NULL    MusicSrcType = iota
	LIST_SOURCE_CREATE               // 创建的
	LIST_SOURCE_COLLECT              // 收藏的
)

// 播放器模块需要的基本参数
type ServerPlayerBase struct {
	RspId       string
	InnerTts    string
	InnerTtsUrl string

	Action    string
	ActionSrc string

	IgnoreListRepeat bool

	ExtraData string `json:"extraData"`
}

// 服务器返回参数：返回的是歌单的列表
type ServerMusicLists struct {
	MusicLists   []MusicListInfo `json:"data"`
	HasMore      bool            `json:"hasMore"`
	Oftag        string          `json:"oftag,omitempty"` // 分类词
	OftagForShow string          `json:"showTag"`
	PlayMode     MusicPlayMode   `json:"playMode,omitempty"`
	CloudId      string          `json:"cloudId"`
	ModeId       int64           `json:"modeId"`
	IsMatch      bool            `json:"isMatch"`

	ServerPullTts
	ServerPlayerBase

	ServerCmd uint16 `json:"-"`
}

// 服务器返回参数： 返回的是歌单
type ServerMusicList struct {
	MusicList    MusicListInfo `json:"data"`
	HasMore      bool          `json:"hasMore,omitempty"`
	Oftag        string        `json:"oftag,omitempty"` // 分类词
	OftagForShow string        `json:"showTag"`
	PlayMode     MusicPlayMode `json:"playMode,omitempty"`
	CloudId      string        `json:"cloudId"`
	ModeId       int64         `json:"modeId"`
	IsMatch      bool          `json:"isMatch"`

	ServerPullTts
	ServerPlayerBase

	ServerCmd uint16 `json:"-"`
}

// 服务器返回参数： 返回歌曲id的详细信息
type ServerSongDetail struct {
	Song SongInfoDetail `json:"data"`

	ServerPullTts
}

// 服务器返回参数： 返回歌曲id的播放信息
type ServerSongPlay struct {
	SongPlay SongPlayInfo `json:"songPlayInfo"`
}

//歌单详情，服务器返回结构
type MusicPlayListDetail struct {
	Id         int    `json:"id"`
	Name       string `json:"name"`
	TrackCount int    `json:"trackCount"`
}

// 服务器返回参数： 返回歌曲id的详细信息
type MusicPlayListInfo struct {
	ListInfo MusicPlayListDetail `json:"playlist"`
}

//电台详情，服务器返回结构
type RadioPlayListDetail struct {
	Id           int    `json:"id"`
	Album        string `json:"album"`
	ProgramCount int    `json:"programCount"`
}

// 服务器返回参数： 返回歌曲id的详细信息
type RadioPlayListInfo struct {
	ListInfo RadioPlayListDetail `json:"data"`
}

// 消息通知状态合集，后续提醒的状态也可以添加在其中
type IsNotify struct {
	IsAlarm  bool
	IsAgency bool
}

type BirthdayInfo struct {
	HasBirthDay    bool       `json:"hasBirthDay"`
	SongList       []SongInfo `json:"songList"`
	Tts            string     `json:"tts"`
	CurMode        int64      `json:"curMode"`
	ModeName       string     `json:"modeName"`
	HasWakeUpScene bool       `json:"hasWakeUpScene"`
}

type WeatherResp struct {
	Tts     string      `json:"tts"`
	Weather WeatherInfo `json:"weather"`
}
type WeatherInfo struct {
	Tts2              string `json:"tts2"`
	MaxTemperature    string `json:"maxTemperature"`
	MinTemperature    string `json:"minTemperature"`
	CurTemperature    string `json:"currTemperature"`
	WeatherPhenomenon string `json:"weahterPhenomenon"`
	City              string `json:"city"`
}
type BirthdaySQL struct {
	HasCheck bool   // 是否播放过
	Date     string // 年月日
}

// 音乐播放的过滤器
type MusicFilter struct {
	SongId     *list.List
	AlbumId    *list.List
	ArtistName *list.List
	lock       sync.RWMutex
}

const (
	SONG_ID_FILTER int8 = iota + 1
	ARTIST_NAME_FILTER
	ALBUM_ID_FILTER
	LIST_ID_FILTER
)
const (
	NORMAL_SONG int8 = iota
	TOP3_RCMD_SONG
)

type TaskFieldType uint8

const (
	FIELD_NULL TaskFieldType = iota
	FIELD_MUSIC
)

const (
	HISTORY_LIST_MAXLEN = 100
	PLAY_LIST_MAXLEN    = 1000
	//HISTORY_LIST_MAXLEN = 10
	//PLAY_LIST_MAXLEN    = 60

	MUSIC_LIST_MAXLEN = 10000

	START_PAGE MusicLenType = 1
	PAGE_SIZE               = 50
	LIST_SIZE               = 10
	//LIST_SIZE               = 2
	FM_SIZE           = 3
	MUSIC_SHARE_SIZE  = 1
	SONG_SIMILAR_SIZE = 5

	MUSIC_MAX_LEN = 15 * 60 // 15min 最大音乐时长

	PLAYSONG_MUSIC_LIST_MAX_LEN = 2

	INVALID_MUSIC_LEN = 0xffff

	MUSIC_ORDER_NEW = "new"
	MUSIC_ORDER_HOT = "hot"

	MUSIC_PLAY_END_THRESHOLD = 5000 // ms
)

type MusicSrcType uint16 // 歌单来源类型
// 服务器推送的歌单类型
const (
	MUSIC_LIST_NULL MusicSrcType = iota // 没有添加过歌单

	MUSIC_LIST  // 歌单 1
	ALBUM_ID    // 专辑 ID 2
	ARTIST_ID   // 艺人 3
	SINGLE_SONG // 单曲,　拉取URL错误直接播报错误信息
)
const (
	PRIVATE_FM             MusicSrcType = 7 + iota // 私人FM 7
	SIMILAR_SONG                                   // 相似歌曲 ，该接口音响端用不到，cmd直接到服务器，post到音响端时，直接带了推荐的歌曲的
	USER_LISTS_COLLECT                             // 收藏的歌单（歌单列表） 9
	USER_LISTS_CREATE                              // 创建的歌单（歌单列表） 10
	USER_LISTS                                     // 我的歌单：包括创建的歌单和收藏的歌单（歌单列表） 11
	RED_FM                                         // 红心FM 12
	MUSIC_LIST_WORD                                // 分类词歌单 (歌单列表) 13
	MUSIC_LIST_SERACH_WORD                         // 搜索分类词歌单 (歌单列表) 14
	ALBUM_ARTIST_ID                                // 专辑 艺人ID (歌单列表) 15
	SERVER_RCMD                                    // 来点音乐 16
	MUSIC_SHARE_RCMD                               // 云村推荐 17
	MUSIC_SPECIAL_RCMD                             // 特定歌曲推荐
)
const (
	OTHERS MusicSrcType = 99 // 其他
)
const (
	// 榜单以及每日推荐,需要存储播放进度等信息
	NEW_TOPLIST          MusicSrcType = 1000 + iota // 新歌榜 1000
	HOT_TOPLIST                                     // 热歌榜 1001
	DAILY_PUSH                                      // 每日歌曲推荐 1002
	DENON_TOPLIST                                   //  电音榜 1003
	CLASSIC_TOPLIST                                 // 古典音乐榜 1004
	BEATPORT_TOPLIST                                // beatport全球电子舞榜 1005
	ORIGINAL_TOPLIST                                // 原创榜 1006
	SORIGN_TOPLIST                                  // 飙升榜 1007
	ACG_TOPLIST                                     // 云音乐ACG音乐榜 1008
	US_BILLBOARD_TOPLIST                            // 美国billboard周榜 1009
	JP_ORICON_TOPLIST                               //  日本oricon周榜 1010
)
const (
	CH_NEW_TOPLIST MusicSrcType = 2001 + iota // 华语新歌榜 2001
	CH_HOT_TOPLIST                            // 华语热歌榜 2002
)

const (
	JP_NEW_LIST    MusicSrcType = 2201 + iota // 日语新歌
	KOREA_NEW_LIST                            // 韩语新歌
	EU_US_NEW_LIST                            // 欧美新歌
)

const (
	// 歌单type续: 音响端自己定义字段
	DAILY_FM_MIX  MusicSrcType = 2900 + iota // 播放推荐
	MUSIC_LIST_ID                            // 非榜单、每日推荐、专辑时，通过该字段拉取歌曲
)

//通用接口type 大于3000, 大于4000
const (
	MUSIC_COMMON_TYPE_LIST MusicSrcType = 3000 + iota
	RECOMMEND_SONG_LIST                 // 三音推荐
	HISTORY_SONG_LIST                   // 历史播放记录歌单
)

//通用电台接口type 大于4000
const (
	RADIO_COMMON_TYPE_LIST MusicSrcType = 4000 + iota
	NATURAL_SOUND_LIST                  // 自然声歌单
	RADIO_STATION_LIST                  // 电台歌单
)

type MusicListType uint8 // 本地列表类型
const (
	HISTORY_MUSIC_LIST MusicListType = iota
	CUR_MUSIC_LIST
	RANDOM_MUSIC_LIST
	SCENES_MUSIC_LIST
	OTHERS_MUSIC_LIST
	PLAYSONG_MUSIC_LIST // 当前播放和预缓存的歌曲节点列表
)

type MusicPlayMode uint8 // 播放模式
const (
	LIST_ORDER_CYCLE MusicPlayMode = iota
	LIST_RANDOM_CYCLE
	SINGLE_CYCLE
	LIST_ORDER_PLAY //顺序播放，完成后结束播放

	MODE_NULL MusicPlayMode = 255
)

type BizTypeDef uint8 // 业务模式
const (
	BIZ_TYPE_MUSIC         BizTypeDef = iota //音乐
	BIZ_TYPE_NATURAL_SOUND                   //自然声
	BIZ_TYPE_RADIO_STATION                   //电台
)

type NormalListIndexType uint8 // normallist index 的数据类型
const (
	NORMAL_LIST_PAGE NormalListIndexType = iota
	SCENES_LIST_PAGE
	OTHERS_LIST_PAGE
)

type MusicChangeAction uint8 // 音乐播放切换时的动作类型
const (
	ACTION_PLAY_BACK   MusicChangeAction = iota // 播放最后一首
	ACTION_PLAY_FRONT                           // 播放第一首
	ACTION_PLAY_DIRECT                          // 2

	ACTION_ADD_LIST_FM            // 3
	ACTION_NEXT_PAGE_REPLACE_LIST // 4
	ACTION_MISS_PAGE_REPLACE_LIST // 5
	ACTION_LAST_PAGE              // 6

	ACTION_ADD_FM // 7

	ACTION_NEXT_LIST_REPLACE_LIST           // 8
	ACTION_ONLY_ONE_LIST_REPLACE_LIST       // 9
	ACTION_CYCLY_TO_FRONT_LIST_REPLACE_LIST // 10

	ACTION_GET_NEW_LIST_REPLACE_LIST // 11
	ACTION_USER_LIST_CYCLE           // 我的歌单循环：创建的歌单和收藏的歌单

	ACTION_ADD_LIST_MUSIC_SHARE // 13

	ACTION_PRE_PAGE_REPLACE_LIST //14 前一页 page

	ACTION_STOP_PLAYER // 停止播放器

	ACTION_NULL
)

type MusicAction uint8 // 调用音乐播放接口后的执行动作类型
// 调用音乐接口时的返回枚举
const (
	MUSIC_ERR_ACTION MusicAction = iota
	MUSIC_REPLAY_NULL
	MUSIC_REPLAY_ACTION
	MUSIC_SINGLE_ACTION
	MUSIC_RCMD_ACTION
	MUSIC_LISTS_ACTION

	APP_ERR_ACTION // 6
	APP_CARD_ACTION
	APP_NIL_ID_ACTION
	APP_CUR_PAGE_ACTION
	APP_NEXT_PAGE_ACTION

	REPEAT_NULL_ACTION //11

	INTERRUPT_NULL_ACTION //12

	NHD_ERR_ACTION //13
	NHD_LESS_T1_NOT_UPDATE
	NHD_LESS_T1_UPDATE
	NHD_MORE_T1_UPDATE
	NHD_MORE_T1_NOT_UPDATE_DIRECT_URL
	NHD_MORE_T1_NOT_UPDATE_CUR_PAGE
	NHD_MORE_T1_NOT_UPDATE_NEXT_PAGE

	FM_ERR_ACTION //20
	FM_LESS_T1
	FM_MORE_T1

	NORMAL_ERR_ACTION //23
	NORMAL_LESS_T1_NOT_UPDATE
	NORMAL_LESS_T1_UPDATE
	NORMAL_MORE_T1_NOT_UPDATE
	NORMAL_MORE_T1_UPDATE

	SIGNAL_ERR_ACTION //28
	SIGNAL_PLAYING
	SIGNAL_HAS_SONG
	SIGNAL_NOT_HAS_SONG
)

type TtsLevel uint8 // TTS播放的等级
const (
	/* 下面的等级通过tts播放器播放 */
	TTS_LEVEL_1 TtsLevel = iota // 通知播报的内容，都是该等级
	TTS_LEVEL_2
	TTS_LEVEL_3
	TTS_LEVEL_PLAYER_MAX
	/* 下面的等级不通过tts播放器播放 */
	TTS_LEVEL_HIGH // bootdone 之外的tts ，提醒，闹钟，wakeup的播放
	/* todo 兼容之前的版本保留 */
	TTS_LEVEL_AGENCT
	TTS_LEVEL_INTERACTIVE // 唤醒时互动的level，即使wakeup状态也会播放

	TTS_LEVEL_MAX
)

var (
	// local music list
	LocalMusicList = map[MusicListType]*MusicList{
		HISTORY_MUSIC_LIST:  &MusicList{List: list.New(), CurPosMusic: nil, ListType: HISTORY_MUSIC_LIST},
		CUR_MUSIC_LIST:      &MusicList{List: list.New(), CurPosMusic: nil, ListType: CUR_MUSIC_LIST},
		RANDOM_MUSIC_LIST:   &MusicList{List: list.New(), CurPosMusic: nil, ListType: RANDOM_MUSIC_LIST},
		SCENES_MUSIC_LIST:   &MusicList{List: list.New(), CurPosMusic: nil, ListType: SCENES_MUSIC_LIST},
		OTHERS_MUSIC_LIST:   &MusicList{List: list.New(), CurPosMusic: nil, ListType: OTHERS_MUSIC_LIST},
		PLAYSONG_MUSIC_LIST: &MusicList{List: list.New(), CurPosMusic: nil, ListType: PLAYSONG_MUSIC_LIST},
	}
	CurPosRecTmp      *list.Element = nil // 在准备下一首时，暂时存放当前的节点，其余时间均为nil
	SceneCurPosRecTmp *list.Element = nil

	LocalMusicFilter MusicFilter = MusicFilter{SongId: list.New(), AlbumId: list.New(), ArtistName: list.New()}
	// 记录播放列表歌曲来源信息
	PlayListSrcRec PlayListSrcInfo = PlayListSrcInfo{MusicListId: nil, MusicListIds: nil, MusicListIdIndex: INVALID_MUSIC_LEN,
		MusicListIdsLen: INVALID_MUSIC_LEN, HasInsert: false, HasMore: false, UpdateTime: 0, MusicSrc: MUSIC_LIST_NULL}
	ScenesPlayerListSrc PlayListSrcInfo = PlayListSrcInfo{MusicListId: nil, MusicListIds: nil, MusicListIdIndex: INVALID_MUSIC_LEN,
		MusicListIdsLen: INVALID_MUSIC_LEN, HasInsert: false, HasMore: false, UpdateTime: 0, MusicSrc: MUSIC_LIST_NULL}
	NormalPlayerListSrc PlayListSrcInfo = PlayListSrcInfo{MusicListId: nil, MusicListIds: nil, MusicListIdIndex: INVALID_MUSIC_LEN,
		MusicListIdsLen: INVALID_MUSIC_LEN, HasInsert: false, HasMore: false, UpdateTime: 0, MusicSrc: MUSIC_LIST_NULL}

	// 当前播放模式
	CurPlayingMode MusicPlayMode = LIST_ORDER_CYCLE

	// recinfomap for musicSrcType which need save curMusicIndex
	NewHotDailyRec = [JP_ORICON_TOPLIST - NEW_TOPLIST + 1]MusicSrcTypeRecInfo{
		NEW_TOPLIST - NEW_TOPLIST:          MusicSrcTypeRecInfo{MusicListIndex: 0, MusicListTimeStamp: 0},
		HOT_TOPLIST - NEW_TOPLIST:          MusicSrcTypeRecInfo{MusicListIndex: 0, MusicListTimeStamp: 0},
		DAILY_PUSH - NEW_TOPLIST:           MusicSrcTypeRecInfo{MusicListIndex: 0, MusicListTimeStamp: 0},
		DENON_TOPLIST - NEW_TOPLIST:        MusicSrcTypeRecInfo{MusicListIndex: 0, MusicListTimeStamp: 0},
		CLASSIC_TOPLIST - NEW_TOPLIST:      MusicSrcTypeRecInfo{MusicListIndex: 0, MusicListTimeStamp: 0},
		BEATPORT_TOPLIST - NEW_TOPLIST:     MusicSrcTypeRecInfo{MusicListIndex: 0, MusicListTimeStamp: 0},
		ORIGINAL_TOPLIST - NEW_TOPLIST:     MusicSrcTypeRecInfo{MusicListIndex: 0, MusicListTimeStamp: 0},
		SORIGN_TOPLIST - NEW_TOPLIST:       MusicSrcTypeRecInfo{MusicListIndex: 0, MusicListTimeStamp: 0},
		ACG_TOPLIST - NEW_TOPLIST:          MusicSrcTypeRecInfo{MusicListIndex: 0, MusicListTimeStamp: 0},
		US_BILLBOARD_TOPLIST - NEW_TOPLIST: MusicSrcTypeRecInfo{MusicListIndex: 0, MusicListTimeStamp: 0},
		JP_ORICON_TOPLIST - NEW_TOPLIST:    MusicSrcTypeRecInfo{MusicListIndex: 0, MusicListTimeStamp: 0},
	}
	// 记录每日歌曲推荐播放与否信息
	DailyPushPlayedInfo DailyPushRec = DailyPushRec{HasPlayed: false}

	CurIsNotify IsNotify = IsNotify{IsAlarm: false, IsAgency: false}

	NormalListMap map[NormalListIndexType]*NormalList = map[NormalListIndexType]*NormalList{
		// 记录歌单页面拉取的情况
		NORMAL_LIST_PAGE: &NormalList{List: list.New(), CurPos: nil, HasMore: false, BackIndex: 0},
		SCENES_LIST_PAGE: &NormalList{List: list.New(), CurPos: nil, HasMore: false, BackIndex: 0},
		OTHERS_LIST_PAGE: &NormalList{List: list.New(), CurPos: nil, HasMore: false, BackIndex: 0},
	}

	ReplayMusicVoiceErr bool = false
	// unit test 是否是单元测试
	UintTest bool = false
)
