package globals

import (
	"container/list"
	"fmt"
	"netease_control_center/interfaces/log"
	"runtime"
	"strings"
	"time"
)

var (
	err error
)

/**
该函数废弃
*/
func println(arg ...interface{}) {
	_, file, line, _ := runtime.Caller(1)
	strs := strings.Split(file, "/")
	if len(strs) > 0 {
		file = strs[len(strs)-1]
	}
	fmt.Print("->->->->", file, ":", line)
	fmt.Println(arg)
}

func GetDateStr() string {
	return time.Now().Format("20060102")
}

/**
 *********************************    wifi player api    ************************************
 */
/**
根据当前的播放模式，获取播放列表的索引值
*/
func GetMusicListIndex() MusicListType {
	var tmp MusicListType = CUR_MUSIC_LIST
	switch CurPlayingMode {
	case LIST_ORDER_CYCLE, SINGLE_CYCLE, LIST_ORDER_PLAY:
		tmp = CUR_MUSIC_LIST
	case LIST_RANDOM_CYCLE:
		tmp = RANDOM_MUSIC_LIST
	default:
		log.Println(log.WarningLog, "Err play mode:", CurPlayingMode)

	}
	return tmp
}

func GetCurWifiSongInfo() (*SongInfo, error) {
	if nil != CurPosRecTmp {
		if eVal, ok := CurPosRecTmp.Value.(*SongInfo); ok {
			return eVal, nil
		}
	} else if nil != LocalMusicList[GetMusicListIndex()].CurPosMusic {
		if eVal, ok := LocalMusicList[GetMusicListIndex()].CurPosMusic.Value.(*SongInfo); ok {
			return eVal, nil
		}
	}
	return nil, MusicList_ERR_GET_CUR_INFL
}

func GetScenesSongInfo() (*SongInfo, error) {
	if nil != SceneCurPosRecTmp {
		if eVal, ok := SceneCurPosRecTmp.Value.(*SongInfo); ok {
			return eVal, nil
		}
	} else if nil != LocalMusicList[SCENES_MUSIC_LIST].CurPosMusic {
		if eVal, ok := LocalMusicList[SCENES_MUSIC_LIST].CurPosMusic.Value.(*SongInfo); ok {
			return eVal, nil
		}
	}
	return nil, MusicList_ERR_GET_CUR_INFL
}

/**
 *********************************    page index api    ************************************
 */
func GetPageFromIndex(index MusicLenType, pageSize MusicLenType) *PageNode {
	index += 1 // index下标从0开始的，计算page时需要转化为数量
	var tmp PageNode
	pageIndex := MusicLenType(index / pageSize)
	if 0 != index%pageSize {
		pageIndex += 1
	}

	tmp.PageIndex = MusicLenType(pageIndex)

	return &tmp
}

/**
  获取index所在页的开始index
*/
func GetPageIndexFromIndex(index MusicLenType, pageSize MusicLenType) MusicLenType {
	pageTmp := GetPageFromIndex(index, pageSize)

	out := ((*pageTmp).PageIndex - 1) * pageSize

	return MusicLenType(out)
}

/**
 *********************************    music filter    ************************************
 */
func (this *MusicFilter) WLock() {
	//log.Printf(log.DebugLog, "MusicFilter w lock\n")
	this.lock.Lock()
}

func (this *MusicFilter) WUnlock() {
	//log.Printf(log.DebugLog, "MusicFilter w unlock\n")
	this.lock.Unlock()
}

func (this *MusicFilter) RLock() {
	//log.Printf(log.DebugLog, "MusicFilter R lock\n")
	this.lock.RLock()
}

func (this *MusicFilter) RUnlock() {
	//log.Printf(log.DebugLog, "MusicFilter R unlock\n")
	this.lock.RUnlock()
}

func (this *MusicFilter) Init() {
	if nil == this.SongId {
		this.SongId = list.New()
	}
	if nil == this.AlbumId {
		this.AlbumId = list.New()
	}
	if nil == this.ArtistName {
		this.ArtistName = list.New()
	}

	this.WLock()
	defer this.WUnlock()

	this.SongId.Init()
	this.AlbumId.Init()
	this.ArtistName.Init()

}

func (this *MusicFilter) Push(listType int8, e interface{}) error {
	this.WLock()
	defer this.WUnlock()

	var listTmp *list.List = nil
	switch listType {
	case SONG_ID_FILTER:
		listTmp = this.SongId
	case ALBUM_ID_FILTER:
		listTmp = this.AlbumId
	case ARTIST_NAME_FILTER:
		listTmp = this.ArtistName
	case LIST_ID_FILTER:

	default:
		return List_ERR_UNSUPPORT
	}
	if nil == listTmp {
		return List_ERR_NULL
	}
	if e != nil {
		switch eVal := e.(type) {
		case *string:
			if 0 == listTmp.Len() {
				listTmp.PushBack(e)
			} else {
				for pr := listTmp.Front(); pr != nil; pr = pr.Next() {
					if *(pr.Value.(*string)) == *eVal {
						return nil
					}
				}
				listTmp.PushBack(e)
			}
		default:
			return List_ERR_UNSUPPORT
		}

		/* only for test */
		this.Println(SONG_ID_FILTER)
		this.Println(ALBUM_ID_FILTER)
		this.Println(ARTIST_NAME_FILTER)

		return nil
	}
	return Tts_ERR_NODE_NULL
}

func (this *MusicFilter) Search(e interface{}) bool {
	this.RLock()
	defer this.RUnlock()

	switch eval := e.(type) {
	case *SongInfo:
		if eval == nil {
			return false
		}

		for pr := LocalMusicFilter.SongId.Front(); pr != nil; pr = pr.Next() {
			if eval.Id == *pr.Value.(*string) {
				return true
			}
		}

		for pr := LocalMusicFilter.ArtistName.Front(); pr != nil; pr = pr.Next() {
			//if eval.ArtistName == *pr.Value.(*string) {
			//	return true
			//}
			if IsArtistNameDeny(eval.ArtistName, *pr.Value.(*string)) {
				return true
			}
		}

		for pr := LocalMusicFilter.AlbumId.Front(); pr != nil; pr = pr.Next() {
			if eval.AlbumId == *pr.Value.(*string) {
				return true
			}
		}
	default:
		log.Println(log.ErrorLog, "err type")
	}
	return false
}

/* only for test */
func (this *MusicFilter) Println(listType int8) {
	var listTmp *list.List = nil
	switch listType {
	case SONG_ID_FILTER:
		listTmp = this.SongId
		log.Println(log.DebugLog, "SongId filter:")
	case ALBUM_ID_FILTER:
		listTmp = this.AlbumId
		log.Println(log.DebugLog, "album filter:")
	case ARTIST_NAME_FILTER:
		listTmp = this.ArtistName
		log.Println(log.DebugLog, "artist filter:")
	default:
		return
	}
	if nil == listTmp {
		return
	}

	for pr := listTmp.Front(); nil != pr; pr = pr.Next() {
		log.Printf(log.DebugLog, "id:%s\n", *pr.Value.(*string))
	}
}

func IsArtistNameDeny(songName string, filterSongName string) bool {
	curArtistName := strings.Split(songName, "/")
	filterArtistName := strings.Split(filterSongName, "/")

	//log.Println(log.DebugLog,"curArtist:", curArtistName, ", filterArtistName:",filterArtistName)

	for _, curName := range curArtistName {
		for _, filterName := range filterArtistName {
			if curName == filterName {
				return true
			}
		}
	}

	return false
}

/**
 *********************************    TtsList    ************************************
 */
func (this *TtsList) WLock() {
	//log.Printf(log.DebugLog, "TtsList w lock\n")
	this.lock.Lock()
}

func (this *TtsList) WUnlock() {
	//log.Printf(log.DebugLog, "TtsList w unlock\n")
	this.lock.Unlock()
}

func (this *TtsList) RLock() {
	//log.Printf(log.DebugLog, "TtsList R lock\n")
	this.lock.RLock()
}

func (this *TtsList) RUnlock() {
	//log.Printf(log.DebugLog, "TtsList R unlock\n")
	this.lock.RUnlock()
}

func (this *TtsList) Init() {
	this.WLock()
	defer this.WUnlock()

	if nil == this.List {
		this.List = list.New()
	}
	this.List.Init()
	this.CurPos = nil
}

func (this *TtsList) GetRemoveBack() (*list.Element, error) {
	this.RLock()
	defer this.RUnlock()

	if 0 == this.List.Len() {
		return nil, List_ERR_NULL
	} else {
		tmp := this.List.Back()
		this.List.Remove(tmp)
		return tmp, nil
	}
}

func (this *TtsList) GetLen() int {
	this.RLock()
	defer this.RUnlock()

	if nil == this.List {
		return 0
	} else {
		return this.List.Len()
	}
}

func (this *TtsList) Push(e interface{}) error {
	if e != nil {
		switch eVal := e.(type) {
		case *TtsInfo:
			// 插入需要考虑顺序
			this.WLock()
			defer this.WUnlock()
			if nil == this.List {
				this.List = list.New()
			}
			if 0 == this.List.Len() {
				this.CurPos = this.List.PushBack(e)
			} else {
				var tmp *list.Element = nil
				for pr := this.List.Front(); pr != nil; pr = pr.Next() {
					if eVal.Level <= pr.Value.(*TtsInfo).Level {
						tmp = pr
						break
					}
				}
				if nil == tmp {
					this.CurPos = this.List.InsertAfter(e, this.List.Back())
				} else {
					this.CurPos = this.List.InsertBefore(e, tmp)
				}
			}
		default:
			return List_ERR_UNSUPPORT
		}

		/* only for test */
		this.Println()

		return nil
	}
	return Tts_ERR_NODE_NULL
}

/* only for test */
func (this *TtsList) Println() {
	fmt.Println("TtsList:")
	for pr := this.List.Front(); nil != pr; pr = pr.Next() {
		fmt.Printf("ttsinfo:%s type:%d level:%d\n",
			*(pr.Value.(*TtsInfo).Tts),
			pr.Value.(*TtsInfo).SrcType,
			pr.Value.(*TtsInfo).Level)
	}
}

/**
 *********************************    CbList    ************************************
 */
func (this *CbList) WLock() {
	//	log.Printf(log.DebugLog, "CbList w lock\n")
	this.lock.Lock()
}

func (this *CbList) WUnlock() {
	//	log.Printf(log.DebugLog, "CbList w unlock\n")
	this.lock.Unlock()
}

func (this *CbList) RLock() {
	//	log.Printf(log.DebugLog, "CbList R lock\n")
	this.lock.RLock()
}

func (this *CbList) RUnlock() {
	//	log.Printf(log.DebugLog, "CbList R unlock\n")
	this.lock.RUnlock()
}

func (this *CbList) Init() {
	this.WLock()
	defer this.WUnlock()

	if nil == this.List {
		this.List = list.New()
	}
	this.List.Init()
}

func (this *CbList) Push(e interface{}) error {
	if e != nil {
		switch eval := e.(type) {
		case func(e interface{}, cbType CallCbType):
			// 插入需要考虑顺序
			this.WLock()
			defer this.WUnlock()
			if nil == this.List {
				this.List = list.New()
			}
			this.List.PushBack(e)
		default:
			log.Printf(log.ErrorLog, "cfglist cb func type err:%+v\n", eval)
			return List_ERR_UNSUPPORT
		}

		/* only for test */
		this.Println()

		return nil
	}
	return Tts_ERR_NODE_NULL
}

func (this *CbList) Exec(e interface{}, cbType CallCbType) {
	this.RLock()
	defer this.RUnlock()

	if nil != this.List {
		for pr := this.List.Front(); nil != pr; pr = pr.Next() {
			if cb, ok := pr.Value.(func(e interface{}, cbType CallCbType)); ok {
				cb(e, cbType)
			} else {
				log.Printf(log.ErrorLog, "cfglist cb func type err\n")
			}
		}
	}
}

/* only for test */
func (this *CbList) Println() {
	fmt.Println("CbList:")
	for pr := this.List.Front(); nil != pr; pr = pr.Next() {
		fmt.Printf("Cb:%+v\n", pr)
	}
}

/**
 *********************************    NormalList    ************************************
 */
func (this *NormalList) WLock() {
	//log.Printf(log.DebugLog, "NormalList w lock\n")
	this.lock.Lock()
}

func (this *NormalList) WUnlock() {
	//log.Printf(log.DebugLog, "NormalList w unlock\n")
	this.lock.Unlock()
}

func (this *NormalList) RLock() {
	//log.Printf(log.DebugLog, "NormalList R lock\n")
	this.lock.RLock()
}

func (this *NormalList) RUnlock() {
	//log.Printf(log.DebugLog, "NormalList R unlock\n")
	this.lock.RUnlock()
}

func (this *NormalList) Init() {
	if nil == this.List {
		this.List = list.New()
	}
	this.WLock()
	defer this.WUnlock()
	this.List.Init()
	this.HasMore = false
	this.CurPos = nil
	this.MaxPage = 0
}

func (this *NormalList) GetFirst() (*list.Element, error) {
	this.RLock()
	defer this.RUnlock()

	if nil == this.List || 0 == this.List.Len() {
		return nil, List_ERR_NULL
	} else {
		return this.List.Front(), nil
	}
}

func (this *NormalList) GetLast() (*list.Element, error) {
	this.RLock()
	defer this.RUnlock()

	if nil == this.List || 0 == this.List.Len() {
		return nil, List_ERR_NULL
	} else {
		return this.List.Back(), nil
	}
}

func (this *NormalList) GetNext() (*list.Element, error) {
	this.RLock()
	defer this.RUnlock()

	if nil == this.List || 0 == this.List.Len() {
		return nil, List_ERR_NULL
	} else if nil == this.CurPos {
		return this.List.Front(), nil
	} else {
		tmp := this.CurPos.Next()
		if nil == tmp {
			return this.List.Front(), nil
		} else {
			return tmp, nil
		}
	}
}

func (this *NormalList) GetPre() (*list.Element, error) {
	this.RLock()
	defer this.RUnlock()

	if nil == this.List || 0 == this.List.Len() {
		return nil, List_ERR_NULL
	} else {
		if nil == this.CurPos {
			return this.List.Front(), nil
		} else {
			tmp := this.CurPos.Prev()
			if nil == tmp {
				return this.List.Back(), nil
			} else {
				return tmp, nil
			}
		}
	}
}

func (this *NormalList) GetMissPage() MusicLenType {
	this.RLock()
	defer this.RUnlock()

	pageLen := this.List.Back().Value.(*PageNode).PageIndex
	hasPage := make([]bool, int(pageLen))
	for pr := this.List.Front(); pr != nil; pr = pr.Next() {
		hasPage[pr.Value.(*PageNode).PageIndex-1] = true
	}
	for k, v := range hasPage {
		if !v {
			return MusicLenType(k + 1)
		}
	}
	return INVALID_MUSIC_LEN
}

func (this *NormalList) Push(e interface{}) error {
	if e != nil {
		switch this.ListType {
		case NORMAL_LIST_PAGE:
			switch eVal := e.(type) {
			case *PageNode:
				// 插入需要考虑顺序
				this.WLock()
				defer this.WUnlock()
				if nil == this.List {
					this.List = list.New()
				}
				if 0 == this.List.Len() {
					this.CurPos = this.List.PushBack(e)
				} else {
					var tmp *list.Element = nil
					for pr := this.List.Front(); pr != nil; pr = pr.Next() {
						if eVal.PageIndex < pr.Value.(*PageNode).PageIndex {
							// 该节点的前节点和后节点都不能和插入节点的值相等
							if nil != pr.Prev() && eVal.PageIndex == pr.Prev().Value.(*PageNode).PageIndex {
								goto setCurPos
							}

							if nil != pr.Next() && eVal.PageIndex == pr.Next().Value.(*PageNode).PageIndex {
								goto setCurPos
							}
							tmp = pr
							break
						}
					}
					if nil == tmp {
						// 需要判断该节点是否和最后节点相同
						if eVal.PageIndex == this.List.Back().Value.(*PageNode).PageIndex {
							goto setCurPos
						}
						this.CurPos = this.List.PushBack(e)
					} else {
						this.CurPos = this.List.InsertBefore(e, tmp)
					}
					goto out
				setCurPos:
					for pr := this.List.Front(); pr != nil; pr = pr.Next() {
						if eVal.PageIndex == pr.Value.(*PageNode).PageIndex {
							this.CurPos = pr
							log.Printf(log.DebugLog, "change cur pos of pageIndex\n")
						}
					}
					return NormalList_ERR_INVALID_NODE
				}
			default:
				return List_ERR_UNSUPPORT
			}
		default:
			return List_ERR_UNSUPPORT
		}
	out:
		/* only for test */
		this.Println()

		return nil
	}
	return NormalList_ERR_NODE_NULL
}

/* only for test */
func (this *NormalList) Println() {
	switch this.ListType {
	case NORMAL_LIST_PAGE:
		fmt.Printf("Page list:")
	default:
		fmt.Printf("Default:")
	}
	for pr := this.List.Front(); nil != pr; pr = pr.Next() {
		fmt.Printf("PageIndex:%d\n", pr.Value.(*PageNode).PageIndex)
	}
}

/**
 *********************************    MusicList    ************************************
 */
const (
	LOCK_LOG_ENABLE = false
)

func (this *MusicList) WLock() {
	if LOCK_LOG_ENABLE {
		this.printType()
		//log.Printf(log.DebugLog, " w lock\n")
	}

	this.lock.Lock()
}
func (this *MusicList) WUnlock() {
	if LOCK_LOG_ENABLE {
		this.printType()
		//log.Printf(log.DebugLog, " w unlock\n")
	}
	this.lock.Unlock()
}

func (this *MusicList) RLock() {
	if LOCK_LOG_ENABLE {
		this.printType()
		//log.Printf(log.DebugLog, " R lock\n")
	}
	this.lock.RLock()
}

func (this *MusicList) RUnlock() {
	if LOCK_LOG_ENABLE {
		this.printType()
		//log.Printf(log.DebugLog, " R unlock\n")
	}
	this.lock.RUnlock()
}

func (this *MusicList) printType() {
	switch this.ListType {
	case HISTORY_MUSIC_LIST:
		log.Println(log.DebugLog, "HistoryMusicList:")
	case CUR_MUSIC_LIST:
		log.Println(log.DebugLog, "CurMusicList:")
	case RANDOM_MUSIC_LIST:
		log.Println(log.DebugLog, "RandomMusicList:")
	case SCENES_MUSIC_LIST:
		log.Println(log.DebugLog, "ScenesMusicList:")
	case OTHERS_MUSIC_LIST:
		log.Println(log.DebugLog, "OtherMusicList:")
	case PLAYSONG_MUSIC_LIST:
		log.Println(log.DebugLog, "PlaySongMusicList:")
	default:
		log.Println(log.DebugLog, "Default:")
	}
}

func (this *MusicList) IsNil() bool {
	this.RLock()
	defer this.RUnlock()

	if nil == this.List || 0 == this.List.Len() {
		return true
	} else {
		return false
	}
}

func (this *MusicList) GetFirst() (*list.Element, error) {
	this.RLock()
	defer this.RUnlock()

	if nil == this.List || 0 == this.List.Len() {
		return nil, List_ERR_NULL
	} else {
		return this.List.Front(), nil
	}
}

func (this *MusicList) GetLast() (*list.Element, error) {
	this.RLock()
	defer this.RUnlock()

	if nil == this.List || 0 == this.List.Len() {
		return nil, List_ERR_NULL
	} else {
		return this.List.Back(), nil
	}
}

func (this *MusicList) GetNext() (*list.Element, error) {
	this.RLock()
	defer this.RUnlock()

	if nil == this.List || 0 == this.List.Len() {
		return nil, List_ERR_NULL
	} else if nil == this.CurPosMusic {
		return this.List.Front(), nil
	} else {
		tmp := this.CurPosMusic.Next()
		if nil == tmp {
			return this.List.Front(), nil
		} else {
			return tmp, nil
		}
	}
}

func (this *MusicList) GetPre() (*list.Element, error) {
	this.RLock()
	defer this.RUnlock()

	if nil == this.List || 0 == this.List.Len() {
		return nil, List_ERR_NULL
	} else {
		if nil == this.CurPosMusic {
			return this.List.Front(), nil
		} else {
			tmp := this.CurPosMusic.Prev()
			if nil == tmp {
				return this.List.Back(), nil
			} else {
				return tmp, nil
			}
		}
	}
}

func (this *MusicList) GetCurPos() *list.Element {
	this.RLock()
	defer this.RUnlock()

	if nil != this.List {
		return this.CurPosMusic
	} else {
		return nil
	}
}

func (this *MusicList) GetValidMusicLen() MusicLenType {
	var cnt MusicLenType = 0

	for pr := this.List.Front(); nil != pr; pr = pr.Next() {
		//过滤掉不能播放和用户否定的歌曲
		if pr.Value.(*SongInfo).CanPlay && !LocalMusicFilter.Search(pr.Value.(*SongInfo)) {
			cnt++
		}
	}
	return cnt
}

func (this *MusicList) SetCurPos(curPos *list.Element) {
	this.WLock()
	defer this.WUnlock()

	this.CurPosMusic = curPos
}

func (this *MusicList) Init() {
	this.WLock()
	defer this.WUnlock()

	if nil == this.List {
		this.List = list.New()
	}

	this.List.Init()
	this.CurPosMusic = nil
}

func (this *MusicList) Push(e interface{}, print bool) error {
	this.WLock()
	defer this.WUnlock()

	return this.push(e, print)
}

func (this *MusicList) push(e interface{}, print bool) error {
	if nil == this.List {
		this.List = list.New()
	}

	if e != nil {
		switch this.ListType {
		case PLAYSONG_MUSIC_LIST:
			if PLAYSONG_MUSIC_LIST_MAX_LEN == this.List.Len() {
				this.List.Remove(this.List.Front())
			}

			for pr := this.List.Front(); nil != pr; pr = pr.Next() {
				if pr.Value.(*SongInfo).Id == e.(*SongInfo).Id {
					this.List.Remove(pr)
				}
			}

			this.List.PushBack(e)
		case HISTORY_MUSIC_LIST:
			if nil != this.CurPosMusic {
				// search whether has the music
				for tmpE := this.List.Front(); nil != tmpE; tmpE = tmpE.Next() {
					if tmpE.Value.(*SongInfo).Id == e.(*SongInfo).Id {
						this.List.Remove(tmpE)
						break
					}
				}
				if HISTORY_LIST_MAXLEN == this.List.Len() {
					this.List.Remove(this.List.Back())
				}
			}
			this.List.PushFront(e)
			this.CurPosMusic = this.List.Front()

			//not print history music list
			print = false
		case CUR_MUSIC_LIST, RANDOM_MUSIC_LIST, SCENES_MUSIC_LIST, OTHERS_MUSIC_LIST:
			var tmp *list.Element

			if PLAY_LIST_MAXLEN == this.List.Len() {
				if this.CurPosMusic == this.List.Back() {
					this.List.Remove(this.List.Front())
				} else {
					this.List.Remove(this.List.Back())
				}
			}
			if nil == this.CurPosMusic {
				tmp = this.List.PushBack(e)
			} else {
				tmp = this.List.InsertAfter(e, this.CurPosMusic)
			}

			if tmp.Value.(*SongInfo).CanPlay {
				this.CurPosMusic = tmp
			}
		default:
			return List_ERR_UNSUPPORT
		}
		if print {
			/* only for test */
			this.Println()
		}

		return nil
	}
	return MusicList_ERR_MUSICINFO_NULL
}

func (this *MusicList) LenIndexWithoutSingle() MusicLenType {
	this.RLock()
	defer this.RUnlock()

	var tmp MusicLenType = 0
	for pr := this.List.Front(); nil != pr; pr = pr.Next() {
		if !pr.Value.(*SongInfo).Single {
			tmp++
		}
	}
	return tmp - 1
}

/* only for test */
func (this *MusicList) Println() {
	this.printType()
	index := 0
	for pr := this.List.Front(); nil != pr; pr = pr.Next() {
		log.Printf(log.DebugLog, "[%3d] Id:%s CanPlay:%v Single:%v Rcmd:%v Like:%v os:%v(%v,%v,%v,%v,%v,%v,%v,%v,%+v)\n",
			index,
			pr.Value.(*SongInfo).Id,
			pr.Value.(*SongInfo).CanPlay,
			pr.Value.(*SongInfo).Single,
			pr.Value.(*SongInfo).SongType,
			pr.Value.(*SongInfo).IsLiked,
			pr.Value.(*SongInfo).SourceOs,

			pr.Value.(*SongInfo).ArtistId,
			pr.Value.(*SongInfo).ArtistName,
			pr.Value.(*SongInfo).AlbumId,
			pr.Value.(*SongInfo).AlbumName,
			pr.Value.(*SongInfo).TagName,
			pr.Value.(*SongInfo).MusicListId,
			pr.Value.(*SongInfo).MusicSrc,
			pr.Value.(*SongInfo).Gain,
			pr.Value.(*SongInfo).Tts)
		index++
	}
}

// e : *SongInfo / *string
func (this *MusicList) Search(e interface{}, setCurPos bool) (songInfo *SongInfo, index MusicLenType, ret bool) {
	this.RLock()
	defer this.RUnlock()

	if nil == e {
		log.Println(log.WarningLog, "param nil when search")
		return nil, MUSIC_LIST_MAXLEN, false
	}
	ret = false
	index = 0
	switch this.ListType {
	case CUR_MUSIC_LIST, RANDOM_MUSIC_LIST, SCENES_MUSIC_LIST, OTHERS_MUSIC_LIST, PLAYSONG_MUSIC_LIST:
		var songId *string = nil

		switch eVal := e.(type) {
		case *SongInfo:
			songId = &eVal.Id
		case *string:
			songId = eVal
		default:
			log.Println(log.WarningLog, "param err when search")
			return nil, MUSIC_LIST_MAXLEN, false
		}

		for pr := this.List.Front(); pr != nil; pr = pr.Next() {
			if pr.Value.(*SongInfo).Id == *songId {
				ret = true
				if setCurPos {
					this.CurPosMusic = pr
				}
				songInfo = pr.Value.(*SongInfo)
				break
			}
			if !pr.Value.(*SongInfo).Single {
				index++
			}
		}
	default:
		return nil, MUSIC_LIST_MAXLEN, false
	}
	return songInfo, index, ret
}

func (this *MusicList) ReplaceByList(newList *MusicList) error {
	switch this.ListType {
	case HISTORY_MUSIC_LIST, CUR_MUSIC_LIST, SCENES_MUSIC_LIST, OTHERS_MUSIC_LIST:
		this.Init()
		err = this.AddByList(newList)
		if nil == err {
			tmp := getCanplayNode(this.List)
			if nil != tmp {
				this.CurPosMusic = tmp
			}
		}
	case RANDOM_MUSIC_LIST:

	default:
		return List_ERR_UNSUPPORT
	}
	return err
}

func (this *MusicList) AddByList(newList *MusicList) error {
	this.WLock()
	defer this.WUnlock()

	switch this.ListType {
	case HISTORY_MUSIC_LIST, CUR_MUSIC_LIST, SCENES_MUSIC_LIST, OTHERS_MUSIC_LIST:
		this.List.PushBackList(newList.List)
	case RANDOM_MUSIC_LIST:

	default:
		return List_ERR_UNSUPPORT
	}
	return nil
}

func (this *MusicList) ReplaceBySlice(music *[]SongInfo, len MusicLenType, offset MusicLenType, topIndex MusicLenType) error {
	switch this.ListType {
	case HISTORY_MUSIC_LIST, CUR_MUSIC_LIST, RANDOM_MUSIC_LIST, SCENES_MUSIC_LIST, OTHERS_MUSIC_LIST:
		this.Init()
		err = this.AddBySlice(music, len, offset, topIndex)
		if nil == err {
			tmp := getCanplayNode(this.List)
			if nil != tmp {
				this.CurPosMusic = tmp
			}
		}
	default:
		return List_ERR_UNSUPPORT
	}
	return err
}

func (this *MusicList) AddBySlice(music *[]SongInfo, len MusicLenType, offset MusicLenType, topIndex MusicLenType) error {
	this.WLock()
	defer this.WUnlock()

	var tmpCurListElement *list.Element = nil
	var index *[]int

	switch this.ListType {
	case HISTORY_MUSIC_LIST, CUR_MUSIC_LIST, SCENES_MUSIC_LIST, OTHERS_MUSIC_LIST:
		index = GetOrderSlice(int(len), int(offset))

	case RANDOM_MUSIC_LIST:
		index = GetRandSlice(int(len), int(offset), int(topIndex))
		if nil == index {
			index = GetOrderSlice(int(len), int(offset))
			log.Println(log.WarningLog, "get rand slice fail, get order slice instead")
		}

	default:
		return List_ERR_UNSUPPORT
	}

	for k, v := range *music {
		if "" != v.Id {
			err = this.push(&(*music)[(*index)[k]], false)
			if nil != err {
				log.Println(log.ErrorLog, err.Error())
				return err
			}
			if nil != this.CurPosMusic && this.CurPosMusic.Value.(*SongInfo).CanPlay &&
				nil == tmpCurListElement {
				tmpCurListElement = this.CurPosMusic
			}
		}
	}
	if nil != tmpCurListElement {
		this.CurPosMusic = tmpCurListElement
	}
	this.Println()
	return nil
}

/**
从头部/尾部开始　获取第一个可以播放的
*/
func (this *MusicList) GetValidFrontBackSong(front bool) *SongInfo {
	this.RLock()
	defer this.RUnlock()
	if front {
		for pr := this.List.Front(); pr != nil; pr = pr.Next() {
			if eVal, ok := pr.Value.(*SongInfo); ok {
				if eVal.CanPlay {
					return eVal
				}
			}
		}
	} else {
		for pr := this.List.Back(); pr != nil; pr = pr.Prev() {
			if eVal, ok := pr.Value.(*SongInfo); ok {
				if eVal.CanPlay {
					return eVal
				}
			}
		}
	}

	return nil
}

func (this *MusicList) GetValidNext() (bool, MusicLenType) {
	this.RLock()
	defer this.RUnlock()

	var cnt MusicLenType = 0
	for {
		this.CurPosMusic, err = this.GetNext()
		cnt++
		if nil != err {
			log.Println(log.ErrorLog, err.Error())
			return false, cnt
		}

		if this.CurPosMusic.Value.(*SongInfo).CanPlay {
			break
		} else if this.CurPosMusic == this.List.Back() {
			this.CurPosMusic = this.List.Front()
			cnt++
			if this.CurPosMusic.Value.(*SongInfo).CanPlay {
				break
			}
		}
		if cnt >= MusicLenType(this.List.Len()) {
			return false, cnt
		}
	}
	return true, cnt
}

func (this *MusicList) GetValidNextIncludeCur() (bool, MusicLenType) {
	this.RLock()
	defer this.RUnlock()

	var cnt MusicLenType = 0
	if nil == this.CurPosMusic {
		return false, cnt
	}

	for {
		if this.CurPosMusic.Value.(*SongInfo).CanPlay {
			break
		} else if this.CurPosMusic == this.List.Back() {
			this.CurPosMusic = this.List.Front()
			cnt++
			if this.CurPosMusic.Value.(*SongInfo).CanPlay {
				break
			}
		}
		if cnt >= MusicLenType(this.List.Len()) {
			return false, cnt
		}
		this.CurPosMusic, err = this.GetNext()
		cnt++
		if nil != err {
			log.Println(log.ErrorLog, err.Error())
			return false, cnt
		}
	}
	return true, cnt
}

func (this *MusicList) GetValidPre() (bool, MusicLenType) {
	this.RLock()
	defer this.RUnlock()

	var cnt MusicLenType = 0
	for {
		this.CurPosMusic, err = this.GetPre()
		cnt++
		if nil != err {
			log.Println(log.ErrorLog, err.Error())
			return false, cnt
		}

		if this.CurPosMusic.Value.(*SongInfo).CanPlay {
			break
		} else if this.CurPosMusic == this.List.Front() {
			this.CurPosMusic = this.List.Back()
			cnt++

			if this.CurPosMusic.Value.(*SongInfo).CanPlay {
				break
			}
		}
		if cnt >= MusicLenType(this.List.Len()) {
			return false, cnt
		}
	}
	return true, cnt
}

func getCanplayNode(listPtr *list.List) *list.Element {
	var tmp *list.Element = listPtr.Front()
	for {
		if tmp.Value.(*SongInfo).CanPlay {
			return tmp
		} else {
			if tmp == listPtr.Back() {
				return nil
			} else {
				tmp = tmp.Next()
			}
		}
	}
	return nil
}
