
PLAYER_STATE_UNSTARTED	= -1;
PLAYER_STATE_ENDED		= 0;
PLAYER_STATE_PLAYING	= 1;
PLAYER_STATE_PAUSED		= 2;
PLAYER_STATE_BUFFERING	= 3;
SHORT_DURATION_FILTER = 80;	///< 60초보다 작은 곡은 필터링한다.

var doBufferCheckIntervalMiliSeconds = 250;			///< timer 동작하는 시간(밀리세컨드)

var imageSearch;
var lyricsSearch;
var bShowLog = false;
var strLog = "";

var musicChartRequest = null;
var lyricsHttpRequest = null;

//var playingIndex = -1;	/// start from top is -1

var currentPlayingIndex = -1;
var currentSearchingIndex = -1;

var ytplayer = null;
var ytplayerBack = null;

var playerPlaying = null;	///< 현재 플레이 중인 플레이어
var playerCaching = null;	///< 현재 캐싱 중인 플레이어

var artists = [];		///< 가수명
var titles = [];		///< 곡명
var backgrounds = [];	///< 이 곡이 있는 플레이 리스트의 배경 색깔. 다양한 상황에 따라 색을 변하게 해준다.
var playSuccessResultIndex = [];		///< 검색 후 몇번째 결과가 플레이 성공했나. 첫번째 검색 결과 플레이에 실패하면 +1 을 해준다.
var playlistSource = "";	///< 이 플레이리스트의 이름

var nextSongPlayForce = false;		///< 다음곡을 사용자가 직접 선택했으면 true. 2개의 플레이어를 쓰는 모드에서, 다음곡이 준비되었을 때 이 값이 true 이면 바로 다음곡으로 넘어간다.
var nextSongPlayForceInput = false; ///< 바로 다음곡을 준비되었는지 체크하면 지금 준비 중인 곡이 바로 실행되므로, 검색하고 다른 것을 준비할 때 체크하기 위한 변수

/// 랜덤 플레이시에 여기에 모든 곡의 index 를 넣고 섞은 후, 여기서 하나씩 꺼내서 플레이한다. 비어있으면 다시 index 넣고 섞는다.
var randomQueue = [];

var noSearchResultCount = 0;			///< 검색 결과가 없을때 무한반복되는것을 막기위한 변수

var defaultBackgroundColor = "";	///< 기본 배경색은 투명
var cannotSearchBackgroundColor = "#c9c047";
var playFailBackgroundColor = "#c97159";

var playingWidth = 300;
var playingHeight = 300;

var cachingWidth = 100;
var cachingHeight = 100;

var cachingVideoID = "";
var cachingSongInfo = "";
var cachingVideoTitle = "";

var cachingIndex = 0;
var cachingQueryWord = "";

var bufferingStartTime = getCurrentTime();		///< 버퍼링을 시작한 시각을 기록. smart buffering 을 위한 변수

//현재 검색중이면 true
var bSearching = false;
var lastSearchTime = getCurrentTime();
var lastSearchString = "";

/// 현재 플레이 중인 목록의 종류
var listRequestType = "hot"; // or "mylist"

function IsChecked(elementID)
{
	var cb = document.getElementById(elementID);

	if (cb && cb.checked == true)
	{
		return true;
	}
	return false;
}

function onPlayerStateChange1(newState)
{
	/* This event is fired whenever the player's state changes.
	 * Possible values are unstarted (-1), ended (0), playing (1), paused (2), buffering (3), video cued (5).
	 * When the SWF is first loaded it will broadcast an unstarted (-1) event.
	 * When the video is cued and ready to play it will broadcast a video cued event (5). */

	//statusMsg("player1 state change : " + newState);
	
	if ( newState == PLAYER_STATE_ENDED)
	{
		onPlayerEnd();
	}
}

function onPlayerStateChange2(newState)
{
	//statusMsg("player2 state change : " + newState);

	if ( newState == PLAYER_STATE_ENDED)
	{
		onPlayerEnd();
	}
}

function startPlaying()
{
	setInterval(onTimer, doBufferCheckIntervalMiliSeconds);
	
	if ( ytplayer == null )
	{
		alert("ytplayer is null");
		return;
	}
	
	playerPlaying.playVideo();
    listRequest();
}

/// 이 함수는 youtube 플레이어가 로드되면 자동으로 불려지는 함수. 특별히 set 을 하지 않아도 이 함수 이름으로 불려진다.
function onYouTubePlayerReady(playerId)
{
    statusMsg("YouTube player ready : " + playerId);
    
    if ( playerId == "player1" )
    {
        ytplayer = document.getElementById("ytPlayer");
        ytplayer.addEventListener("onError", "onPlayerError");
        ytplayer.addEventListener("onStateChange", "onPlayerStateChange1");
        
        if ( IsDoubleCacheMode() )
        {
        	loadPlayer();
        }
        else
        {
        	playerPlaying = ytplayer;
        	playerCaching = null;
        	startPlaying();
        }
        $("mainDiv").style.marginLeft = "auto";
        $("mainDiv").style.marginRight = "auto";
        $("mainDiv").style.width = playingWidth + "px";
        

    }
    else if ( playerId == "player2" )
    {
        ytplayerBack = document.getElementById("ytPlayerBack");
        ytplayerBack.addEventListener("onError", "onPlayerError");
        ytplayerBack.addEventListener("onStateChange", "onPlayerStateChange2");

        if ( IsChecked("caching_small_size") )
        {
            ytplayerBack.height = cachingHeight;
            ytplayerBack.width = cachingWidth;
        }
        
    	playerPlaying = ytplayer;
    	playerCaching = ytplayerBack;
        startPlaying();

        $("mainDiv").style.marginLeft = "auto";
        $("mainDiv").style.marginRight = "auto";
        a = ((parseInt(playingWidth)+0)*2);
        $("mainDiv").style.width = a + "px";
    }
    else
    {
    	alert("Unknown playerid");
    }
}

// This function is called when an error is thrown by the player
function onPlayerError(errorCode)
{
	if ( errorCode == 100 )
	{
		onErrorManage("Not found video(100)");
	}
	else if ( errorCode == 101 || errorCode == 150 )
	{
		onErrorManage("Not allowed playback in embedded player(101,150)");
	}
	else
	{
		onErrorManage("Errorcode : " + errorCode);
	}
}

function onErrorManage(msg)
{
	errorMsg("Error(" + msg + ") " + getSongInfo(currentSearchingIndex));
    
	/// 현재 시도한 것외에 다음 검색 결과가 있으면 다음 결과를 플레이 시도해본다.
    if (imageSearch.results && (playSuccessResultIndex[currentSearchingIndex] + 1) < imageSearch.results.length )
    {
    	statusMsg("현재 비디오에 문제가 있어 다음 검색 결과를 플레이합니다.");
    	playSuccessResultIndex[currentSearchingIndex] = playSuccessResultIndex[currentSearchingIndex] + 1;
    	currentSearchingIndex--;/// 현재 곡 다시 검색
    	startLoadFav();
    }
    else /// 현재 시도한 것 다음 검색 결과가 더 이상 없으면 이 곡은 에러 표시하고 다음곡으로 넘어간다.
    {
    	backgrounds[currentSearchingIndex] = playFailBackgroundColor;
    	startLoadFav();
    }
}

/// 캐시 중이던 플레이어를 play 로 옮기고, play 시킨다. 
function flipPlayer()
{
	statusMsg("Called flipPlayer()");

	var temp = playerPlaying;
	playerPlaying = playerCaching;
	playerCaching = temp;
	
	if ( IsChecked("caching_small_size") )
	{
		playerPlaying.height = playingHeight;
		playerPlaying.width = playingWidth;
		
		playerCaching.height = cachingHeight;
		playerCaching.width = cachingWidth;
	}
	
	playerPlaying.playVideo();
}

function playCachingPlayerAndFlip()
{
	/// 캐쉬된 플레이어를 플레이시킨다.
	flipPlayer();

	currentPlayingIndex = cachingIndex; 

	/// 현재 플레이하는 정보를 표시한다.
	markCurrentPlaying(currentPlayingIndex);

	
	// 타이틀을 설정한다.
	document.title = cachingSongInfo;

	/// 플레이하는 동영상의 제목을 표시해준다.
	SetVideoInfo(cachingVideoTitle);
	
	SetPlayInfo(cachingSongInfo);

	backgrounds[currentPlayingIndex] = defaultBackgroundColor;
	
	/// 가사를 불러온다.
	startLyricsSearch(cachingQueryWord);

	/// 다음 곡을 검색시킨다.
	nextSongPrepare();
}

function getRandomIndex(maxLen)
{
	return Math.ceil(Math.random() * 5000) % maxLen;
}

function nextSongPrepare()
{
	/// 다음 곡을 미리 불러온다.
	if ( IsRandom() )
	{
		if ( randomQueue.length == 0 )
		{
			makeRandomQueue();
		}
		
		nextSongIndex = randomQueue.pop();
		
		searchAbsoluteIndex(nextSongIndex);
	}
	else
	{
		startLoadFav();
	}
}

function searchRelativeIndex(relativeIndex)
{
    statusMsg("searchRelativeIndex()");
    bSearching = true;
    
    currentSearchingIndex = (currentSearchingIndex + relativeIndex) % artists.length;
    
    if ( currentSearchingIndex < 0 )
    {
    	currentSearchingIndex += artists.length;
    }
    
    searchAbsoluteIndex(currentSearchingIndex);
}

function searchAbsoluteIndex(absoluteIndex)
{
	statusMsg("Search abs : " + absoluteIndex);
	currentSearchingIndex = absoluteIndex;
	
    queryWord = getMoreSearch() + " ";
    
    //queryWord += "mv ";
    queryWord += artists[absoluteIndex] + " " + titles[absoluteIndex];
    
    lastSearchString = queryWord;
    lastSearchTime = getCurrentTime(); 
    
	startVideoSearch(queryWord);
}

function onPlayerEnd()
{
    /// repeat 가 check 되어 있으면 다시 플레이
    if ( IsRepeatChecked() == true )
    {
        playerPlaying.playVideo();
    }
    else
    {
    	if ( IsDoubleCacheMode() )
    	{
    		if ( IsReadyNextSong(playerCaching) )
    		{
    			playCachingPlayerAndFlip();
    		}
    		else
    		{
    			statusMsg("Replay!!!");
    			Replay();
    		}
    	}
    	else
    	{
    		nextSongPrepare();
    	}
    }
}

var sameLoadingLastLoadedCounter = 0;
var sameLoadingLastLoadedBytes = 0;

function preventVeryLongLoading()
{
	if ( IsChecked("reload_when_error") == false ) return;
	
	var checkPlayer = ytplayer;
	
	if ( IsDoubleCacheMode() )
	{
		checkPlayer = playerCaching;
	}
	
	var totalBytes = checkPlayer.getVideoBytesTotal();	///< 동영상의 전체 크기
	var loadedBytes = checkPlayer.getVideoBytesLoaded();	///< 현재까지 로딩된 크기

	if ( totalBytes >= 0 && loadedBytes >= 0 && totalBytes == loadedBytes )	///< 이미 로딩이 완료된건 체크할 필요없다.
	{
		return;
	}
	
	if ( loadedBytes == sameLoadingLastLoadedBytes || totalBytes < 0 || loadedBytes < 0)
	{
		sameLoadingLastLoadedCounter = sameLoadingLastLoadedCounter + 1; 
	}
	else
	{
		sameLoadingLastLoadedCounter = 0;
		sameLoadingLastLoadedBytes = loadedBytes;
		
		return;
	}
	
	var sameLoadingPeriodSeconds = (sameLoadingLastLoadedCounter * doBufferCheckIntervalMiliSeconds) / 1000; 
	
	
	if ( sameLoadingPeriodSeconds > 60 ) ///< 60초 이상 로딩이 멈춰있으면, 
	{
		statusMsg("Reload current video due to loading-timeout");
		
		checkPlayer.loadVideoById(cachingVideoID);	///< 현재것을 다시 로딩한다.
		
		sameLoadingLastLoadedCounter = 0;
	}
}

/// 주기적으로 호출되는 함수
function onTimer()
{
    checkInfiniteSearchWait();

    doMoreBuffer();
    
    preventVeryLongLoading();
}

/// 검색을 요청했는데 무한히 기다리는 경우 처리함수
function checkInfiniteSearchWait()
{
	if ( ((getCurrentTime() - lastSearchTime) > 5000) && bSearching == true )	///< 처리 요청후 5초 지났는데 계속 검색 요청 중이면
	{
		statusMsg("검색 시간이 너무 오래 걸려 다시 요청함.");

		/// 다시 요청한다.
	    --currentSearchingIndex;
		startLoadFav();
	}
}

function errorMsgForBufferInput(msg)
{
	var span = document.getElementById("bufferError");
	
	if ( span )
	{
		span.innerHTML = "<font color='red'>" + msg + "</font>";
	}
}

function isBlockedVideoID(id)
{
	blockedIDs = [ "mq2-YQxsAPA" //< 소녀시대 boys fake
	        , "aaa" //< just for testing
	        ]
	
	for ( i=0; i<blockedIDs.length; ++i )
	{
		if ( blockedIDs[i] == id )
		{
			return true;
		}
	}
	return false;
}


/// 현재 플레이어의 버퍼링된 것이 지금 플레이시키면 중간에 버퍼링 없이 계속 플레이 가능한지를 계산해서 가능하면 true 반환
function IsReadyNextSong(checkingplayer)
{
	var currentTime = getCurrentTime();
	var diffTime = currentTime - bufferingStartTime;	///< 현재까지 로딩하는데 걸린 시간
	var totalBytes = checkingplayer.getVideoBytesTotal();	///< 동영상의 전체 크기
	var loadedBytes = checkingplayer.getVideoBytesLoaded();	///< 현재까지 로딩된 크기
	
	var totalLoadingTime = (diffTime * totalBytes ) / loadedBytes; ///< (loadedBytes : diffTime) = (totalBytes : totalLoadingTime)
	
	var remainLoadingTime = (totalLoadingTime - diffTime) + 5000;		///< 앞으로 로딩하는데 걸리는 시간(여유를 위해 5초 더하기)
	var videoPlayTime = (checkingplayer.getDuration() * 1000);	///< 동영상의 전체 플레이 시간. 밀리세컨드로 맞추기 위해 곱하기 1000 한다. getCurrentTime() 이 밀리세컨드 반환.
	
	//statusMsg("diffTime : " + diffTime);
	//statusMsg("remainLoadingTime : " + remainLoadingTime);
	//statusMsg("videoplaytime : " + videoPlayTime);
	
	if ( (remainLoadingTime < videoPlayTime) ///< 앞으로 남은 로딩시간이 동영상 전체 플레이시간보다 작으면 플레이 시작
			|| totalBytes == loadedBytes )/// 로딩 다 되면
	{
		return true;
	}
	return false;
}

/// 현재 플레이어(혹은 캐시 플레이어)의 버퍼링을 하도록 제어하는 함수
function doMoreBuffer()
{
	var checkPlayer = ytplayer;
	
	if ( IsDoubleCacheMode() )
	{
		checkPlayer = playerCaching;
		checkPlayer.pauseVideo();			///< 캐시중인 노래가 한번씩 플레이되는 문제가 있어서 주기적으로 pause 하도록 함.
	}
	
	if ( IsChecked("more_buffer") || IsDoubleCacheMode() )
	{
		SetBufferingInfo(checkPlayer);
		
		if ( checkPlayer.getCurrentTime() == 0 )/// 현재 위치가 0 일 때만 체크
		{
			var bufferInput = document.getElementById("more_buffer_input");
			
			if ( bufferInput == null )
			{
				errorMsgForBufferInput("buffer input is null");
				return;
			}
			
			var inputValue = 10;
			
			if ( bufferInput.value == "*" )	/// smart buffering
			{
				var minimumBufferBytes = checkPlayer.getVideoBytesTotal() * (5.0 / 100.0);/// 체크 시점은 100분의 5 지점
				
				if ( checkPlayer.getVideoBytesLoaded() <= minimumBufferBytes ) /// 버퍼링한 양이 최소양보다 작으면 임시멈춘다.
				{
					checkPlayer.pauseVideo();
				}
				else
				{
					if ( IsReadyNextSong(checkPlayer) )
					{
						if ( IsDoubleCacheMode() )
						{
							if ( nextSongPlayForce == true )
							{
								nextSongPlayForce = false;
								
								playerPlaying.pauseVideo();
								
								playCachingPlayerAndFlip();
							}
							
							/// double cache 모드일 때는 여기서 play 하는게 아니라, 현재 플레이 중인 곡이 끝났을 때 play 한다.
						}
						else
						{
							checkPlayer.playVideo();
						}
					}
				}
			}
			else
			{
				inputValue = parseInt(bufferInput.value, 10);
				
				if ( inputValue == NaN )
				{
					errorMsgForBufferInput("숫자만 입력가능합니다 : " + err);
					inputValue = 10;
				}
				else if ( inputValue > 90 )
				{
					errorMsgForBufferInput("최대값 90 으로 설정합니다.");
					inputValue = 90;
				}
				else if ( inputValue < 10 )
				{
					errorMsgForBufferInput("최소값은 10 입니다.");
					inputValue = 10;
				}
				else
				{
					errorMsgForBufferInput("");
				}
				
				var minimumBufferBytes = checkPlayer.getVideoBytesTotal() * (inputValue / 100.0);
				
				if ( checkPlayer.getVideoBytesLoaded() <= minimumBufferBytes ) /// 버퍼링한 양이 최소양보다 작으면 임시멈춘다.
				{
					checkPlayer.pauseVideo();
				}
				else
				{
					checkPlayer.playVideo();
				}
			}
		}
	}
}

function getMoreSearch()
{
	var moreSearch = document.getElementById("more_search");

	if ( moreSearch && moreSearch.value )
	{
		return moreSearch.value;
	}
	
    return "";
}

function Replay()
{
    statusMsg("Replay()");

	playerPlaying.seekTo(0, true);
	playerPlaying.playVideo();
}

function Prev()
{
	currentSearchingIndex -= 2;
	startLoadFav();
}

function Next()
{
	if ( IsDoubleCacheMode() )
	{
		playCachingPlayerAndFlip();
	}
	else
	{
		startLoadFav();
	}
}

function startLoadFav()
{
    statusMsg("startLoadFav()");
    searchRelativeIndex(1);
}

/// 현재 시간을 밀리세컨드 숫자 하나로 반환한다.
function getCurrentTime()
{
	return (new Date()).getTime();
}

function getQuality()
{
    urlVars = getUrlVars();
    
    var inputValue = urlVars["fmt"];

    switch ( inputValue )
    {
    case "big":
    	return "big";
    	
    case "noscreen":
    	return "noscreen";
    	
    case "low":
    	return "low";
    	
    case "controlonly":
    	return "controlonly";
    }
    return "normal";
}

function loadPlayer()
{
    // The element id of the Flash embed
    var atts = { id: "ytPlayer" };
    var playerid = "player1";
    var drawDiv = "videoDiv";
    var startVideoID = "o1KK0ayJ_EM";

    /// 처음 플레이어가 로딩되지 않으면, 처음 플레이어를 로딩한다.
    if ( ytplayer == null )
	{
	    statusMsg("Loading player()");
	    
	    if ( IsDoubleCacheMode() )
	    {
		    startVideoID = "SrvLuxuadio";
	    }
	    else
	    {
	    	var player2Div = document.getElementById("videoDivBack");
	    	
	    	if ( player2Div )
	    	{
	    		player2Div.innerHTML = "";
	    	}
	    }
	}
	else if ( IsDoubleCacheMode() ) 	/// At this time, load player2(back)
	{
	    statusMsg("Loading player() phase 2");
	    atts = { id: "ytPlayerBack" };
	    playerid = "player2";
	    drawDiv = "videoDivBack";
	    startVideoID = "SrvLuxuadio";
	}
	else
	{
		//alert("unknwon state");
		return;
	}
    
    var flashVersion = swfobject.getFlashPlayerVersion();
    
    statusMsg("Flash version : " + flashVersion.major + "." + flashVersion.minor);
    
    if ( flashVersion.major < 8 )
    {
    	alert("플래시 버젼이 최소 8 이 되어야 합니다. 현재 버젼 : " + flashVersion.major + "." + flashVersion.minor);
    	alert("재생이 제대로 되지 않을 수 있습니다. 플래시를 업데이트 하기 위해 유튜브 사이트로 이동을 권장합니다.");
    	//location.href="http://www.youtube.com";
    	//return;
    }
    
    // Lets Flash from another domain call JavaScript
    var params = { allowScriptAccess: "always", allowFullScreen: "true" };
    
    // ref : http://code.google.com/intl/ko-KR/apis/youtube/player_parameters.html
    var playerOption = "&autohide=1&enablejsapi=1&playerapiid=" + playerid;
    playerOption += "&fs=1";	/// enable fullscreen
    
    if ( getQuality() == "big" )
    {
        playerOption += "&fmt=22&hd=1";	/// best quality(ref : http://hallang.tistory.com/218)
    }
    else if ( getQuality() == "noscreen" || getQuality() == "low" || getQuality() == "controlonly" )
    {
    	playerOption += "&fmt=17";
    }
    else
    {
        playerOption += "&fmt=34";	/// normal quality
    }
    playerOption += "&showsearch=0";
    playerOption += "&showinfo=0";
    playerOption += "&rel=0";
    
    playerOption += "&color1=303838";		///< border color
    //playerOption += "&color2=000000";		///< frame color
    
    var width = "402";
    var height = "300";

    if ( getQuality() == "noscreen" )
    {
        width = "1";
        height = "1";
    }
    else if ( getQuality() == "controlonly" )
    {
    	width = "402";
    	height = "25";
    }
    else if ( getQuality() == "low" )
    {
        width = "176";
        height = "144";
    }
    else if ( getQuality() == "big" )
    {
        width = "960";
        height = "720";
    }
    playingWidth = width;
    playingHeight = height;

    statusMsg("Embeding SWF : " + playerid);
    swfobject.embedSWF("http://www.youtube.com/v/" + startVideoID +
                       playerOption,
                       drawDiv,
                       width, height,	// width, height
                       "8", null, null, params, atts);
}

/// 플레이리스트의 모든 백그라운드색을 지운다.
function playlistClearBackground()
{
	for ( i=0; i<artists.length; ++i)
	{
		var entry = document.getElementById("playlistid" + i);
		
		if ( entry )
		{
			entry.style.background = backgrounds[i];
			entry.style.fontSize = "100%";
			entry.style.fontWeight = "normal";
		}
	}
}

// 현재 플레이 중인 곡 표시
function markCurrentPlaying(currentIndex)
{
	var currentPlaylist = document.getElementById("playlistid" + currentIndex);
	
	if ( currentPlaylist )
	{
		/// 전체 리스트의 색을 지우고,
		playlistClearBackground();
		
		/// 현재 플레이중인 곡만 색을 넣음.
		currentPlaylist.style.background = "#E3DAAD";
		
		/// 폰트 크기 키움
		currentPlaylist.style.fontSize = "200%";
		
		/// 굵게
		currentPlaylist.style.fontWeight = "bold"; 
	}
}

function redrawPlaylist()
{
	playlistClearBackground();
	markCurrentPlaying(currentPlayingIndex);
}

function IsUsingFilterShortResult()
{
	return IsChecked("filter_short_result");
}

function onLyricsSearchComplete()
{
    if (lyricsSearch.results && lyricsSearch.results.length > 0)
    {
    	statusMsg("lyrics result completed");

    	//statusMsg("url : " + lyricsSearch.results[0].url);
    	
    	requestLyrics(lyricsSearch.results[0].url);
    }
    else
    {
    	onLyricsResponse("No lyrics result");
    }
}

function onSearchComplete()
{
    statusMsg("Video search completed");
	// Check that we got results
    if (imageSearch.results && imageSearch.results.length > 0)
    {
		// Loop through our results, printing them to the page.
		var results = imageSearch.results;
		
		noSearchResultCount = 0;
		
		//statusMsg("playSuccessResultIndex[currentSearchingIndex] : " + playSuccessResultIndex[currentSearchingIndex]);
		if ( playSuccessResultIndex[currentSearchingIndex] < results.length )
		{
			var result = results[playSuccessResultIndex[currentSearchingIndex]];

			/// url 에서 videoID 를 추출한다. original url like http://www.youtube.com/v/q5GqAvEvvWo&fs=1&source=uds&autoplay=1
			searchedVideoID = result.playUrl.substr(25,11);
			
			statusMsg("Searched VideoID : " + searchedVideoID);
			
			if ( isBlockedVideoID(searchedVideoID) == true )
			{
				onErrorManage("Blocked Video ID");
				return;
			}

			if ( IsUsingFilterShortResult() == true )	/// 짧은 동영상은 필터링하는 옵션이 켜져 있으면
			{
				if ( result.duration < SHORT_DURATION_FILTER ) /// 현재 
				{
					onErrorManage("너무 짧은 플레이 시간");
					return;
				}
			}
			
			if(ytplayer)
			{
				
				bufferingStartTime = getCurrentTime();

				if ( IsDoubleCacheMode() )
				{
					SetNextSongInfo("Next song : " + getSongInfo(currentSearchingIndex));
					
					/// 타이틀을 저장해두어, 나중에 play 할 때 설정한다.
					cachingSongInfo = getSongInfo(currentSearchingIndex); 
					
					/// 동영상 제목을 저장해두어, 나중에 play 할 때 설정한다.
					cachingVideoTitle = result.titleNoFormatting;
					
					cachingIndex = currentSearchingIndex;
					cachingVideoID = searchedVideoID;

					playerCaching.loadVideoById(searchedVideoID);
					playerCaching.playVideo();
					playerCaching.pauseVideo();
					
					if ( nextSongPlayForceInput )
					{
						nextSongPlayForceInput = false;
						nextSongPlayForce = true;
					}
				}
				else
				{
					currentPlayingIndex = currentSearchingIndex;
					
					// 타이틀을 설정한다.
					document.title = getCurrentSongInfo();
					
					SetPlayInfo(getCurrentSongInfo());
					
					/// 플레이하는 동영상의 제목을 표시해준다.
					SetVideoInfo(result.titleNoFormatting);
					
					// 현재 플레이 중인 곡 표시
					markCurrentPlaying(currentPlayingIndex);
					
					backgrounds[currentSearchingIndex] = defaultBackgroundColor;

					playerPlaying.loadVideoById(searchedVideoID);
				}
				
				statusMsg("Load " + titles[currentSearchingIndex] + " of " + artists[currentSearchingIndex]);
				bSearching = false;
				
				if ( IsDoubleCacheMode() )
				{
					cachingQueryWord = queryWord;
				}
				else
				{
				    startLyricsSearch(queryWord);
				}
			}
			else
			{
				statusMsg("ytplayer is null");
			}
		}
	}
	else
	{
	    statusMsg("search result is null");
	    
	    // title 에 ( 가 있으면 ( 뒤로 없앤 후 다시 검색한다.
	    var searchResult = titles[currentSearchingIndex].indexOf("(");
	    
	    if ( searchResult == -1 )    ///< ( 가 없으면
	    {
		    ++noSearchResultCount;
		    
		    if ( noSearchResultCount >= artists.length )
		    {
		    	statusMsg("너무 많은 곡의 검색결과가 없습니다. 검색을 중지합니다.");
		    	redrawPlaylist();
		    	return;
		    }
		    
	        /// 다음 노래 재생
	        statusMsg("!!!!!! " + titles[currentSearchingIndex] + " : " + artists[currentSearchingIndex] + " cannot find. next song play !!!!!");
	        
	        backgrounds[currentSearchingIndex] = cannotSearchBackgroundColor;
	        redrawPlaylist();
	        startLoadFav();
	    }
	    else    /// ( 가 있으면 ( 제거 후 다시 검색 시도
	    {
	        statusMsg("remove (" + searchResult);
	        titles[currentSearchingIndex] = titles[currentSearchingIndex].substring(0, searchResult);
	        currentSearchingIndex = currentSearchingIndex - 1;
	        startLoadFav();
	    }
	}
}

function getSongInfo(index)
{
    return titles[index] + " - " + artists[index];
}

function getCurrentSongInfo()
{
    return getSongInfo(currentSearchingIndex);
}

function startLyricsSearch(queryWord)
{
	statusMsg("start lyrics search : " + queryWord);
	lyricsSearch = new google.search.WebSearch();
	lyricsSearch.setSiteRestriction("www.inmuz.com");
	lyricsSearch.setSearchCompleteCallback(this, onLyricsSearchComplete, null);
	lyricsSearch.execute(queryWord);
}

function startVideoSearch(queryWord)
{
	imageSearch = new google.search.VideoSearch();
	imageSearch.setSearchCompleteCallback(this, onSearchComplete, null);
	
	statusMsg("<a href='http://www.youtube.com/results?search_query=" + queryWord.replace(" ", "+") + "' target='_blank'>" + "QueryWord : " + queryWord + "</a>");
	statusMsg(getCurrentSongInfo() + " 검색 중... ");

	imageSearch.execute(queryWord);
}

function getDownloadURL(youtubeurl)
{
	url = "http://keepvid.com/?url=" + encodeURIComponent(youtubeurl);
	return url;
}

function makePlaylistTable()
{
    var playlistDiv = document.getElementById("playlist");

    var tempHTML = "<table>";

    tempHTML += "<tr>";
    tempHTML += "<td colspan='4' align='center'>";
    tempHTML += playlistSource;
    tempHTML += "</td>";
    tempHTML += "</tr>";

    tempHTML += "<tr>";
    tempHTML += "<th>Rank</th>";
    tempHTML += "<th>Title</th>";
    tempHTML += "<th>Artist</th>";
    tempHTML += "</tr>";
    
    for ( i=0; i<titles.length; ++i)
    {
        tempHTML += "<tr id='playlistid" + i + "'>";
        
        	tempHTML += "<td align='center'>" + (i+1) + "</td>";
            tempHTML += "<td><a href='#' onclick='playIndexByUserInput(" + i + ")' title='" + titles[i] + " 재생하기" + "'>" + titles[i] + "</a></td>";
            tempHTML += "<td><a href='http://search.daum.net/search?q=" + artists[i] + "' target='_blank'>" + artists[i] + "</a></td>";
            
        tempHTML += "</tr>";
    }
    tempHTML += "</table>";
    playlistDiv.innerHTML = tempHTML;
}

function onMusicChartResponse(data)
{
	///statusMsg("onMusicChartResponse() called");
    if ( data === null )
    {
        statusMsg("Cannot receive or parse top song list");
        return;
    }
    statusMsg("Parsing xml data");
    
    source = data.getElementsByTagName("source");
    
    songs = data.getElementsByTagName("artist");

    var maxSongLimit = 9999;

	statusMsg("GetMaxSongLimit() : " + GetMaxSongLimit());

    if ( GetMaxSongLimit() != 0 )
    {
    	maxSongLimit = GetMaxSongLimit();
    }
    
    artists = [];
    for ( i=0; i<songs.length; ++i)
    {
     //   statusMsg("Rank : " + i);
       // statusMsg(songs.item(i).firstChild.nodeValue);
        artists.push(songs.item(i).firstChild.nodeValue);
        
        if ( artists.length == maxSongLimit )
        {
        	break;
        }
    }
    
    songs = data.getElementsByTagName("title");

    titles = [];
    backgrounds = [];
    playSuccessResultIndex = [];
    
    for ( i=0; i<songs.length; ++i)
    {
        //statusMsg(songs.item(i).firstChild.nodeValue);
        titles.push(songs.item(i).firstChild.nodeValue);
        
        backgrounds.push(defaultBackgroundColor);
        playSuccessResultIndex.push(0);

        if ( titles.length == maxSongLimit )
        {
        	break;
        }
    }

    playlistSource = source[0].firstChild.nodeValue;

    makePlaylistTable();
    
    statusMsg("Parsing music chart success");
    
    startLoadFav();
}

function playIndexByUserInput(i)
{
	nextSongPlayForceInput = true;
	
	playIndex(i);
}

function playIndex(i)
{
	currentSearchingIndex = i-1;    /// startLoadFav() 에서 +1 을 하므로 -1 값을 준다.
    startLoadFav();
}

function onLyricsResponse(res)
{
	statusMsg("Receive lyrics result");
	var result = "No result";

	if ( res != null )
	{
		result = res;
	}
	
	var lyricsDiv = document.getElementById("lyrics");
	
	if ( lyricsDiv )
	{
		lyricsDiv.innerHTML = result;
	}
	else
	{
		statusMsg("lyricsDiv is null");
	}
}

function lyricsRequestHandler()
{
    if ( lyricsHttpRequest.readyState == 4 && lyricsHttpRequest.status == 200)
    {
        //statusMsg("Check lyrics chart response");
        
        if ( lyricsHttpRequest.responseText == null )
        {
        	//statusMsg("llll null");
        	onLyricsResponse(null);
        }
        
      	onLyricsResponse(lyricsHttpRequest.responseText);
    }
    else if (lyricsHttpRequest.readyState == 4 && lyricsHttpRequest.status != 200)
    {
        // fetched the wrong page or network error...
    	onLyricsResponse(null);
    }
}

function musicChartRequestHandler()
{
	//statusMsg("musicChartRequestHandler");
    if ( musicChartRequest.readyState == 4 && musicChartRequest.status == 200)
    {
        statusMsg("Check music chart response");
        
        if ( musicChartRequest.responseXML == null )
        {
        	onMusicChartResponse(null);
        }
        
        if( musicChartRequest.responseXML.getElementsByTagName('song'))
        {
            // success!
        	onMusicChartResponse(musicChartRequest.responseXML);
        }
        else
        {
        	onMusicChartResponse(null);
        }
    }
    else if (musicChartRequest.readyState == 4 && musicChartRequest.status != 200)
    {
        // fetched the wrong page or network error...
    	onMusicChartResponse(null);
    }
    else
    {
    	//statusMsg("readyState : " + musicChartRequest.readyState);
    	//statusMsg("this.status : " + musicChartRequest.status);
    }
 }

function statusMsg(msg)
{
    var statusDiv = document.getElementById('status');

    /// status 는 마지막 하나
    statusDiv.innerHTML = msg;

    if ( strLog.length > 50000 )	/// 5000 자 이상이면 500 자 줄임
    {
    	strLog = strLog.slice(4500);
    }
    
    /// log 는 모두 기록
    strLog += msg + "<br>";

    if ( bShowLog )
    {
    	refreshLog();
    }
}

function errorMsg(msg)
{
	/// 에러가 하나라도 있으면 status 배경색을 바꾼다.
    var statusDiv = document.getElementById('status');
    statusDiv.style.background = "#ff7777";
	
	statusMsg("<font color='red'>" + "[ERROR] " + msg + "</font>");
}

function requestLyrics(url)
{
	lyricsHttpRequest = newXMLHttpRequest();
    
    if ( lyricsHttpRequest == null ) return;
    
    lyricsHttpRequest.onreadystatechange = lyricsRequestHandler;
    lyricsHttpRequest.open("GET", "/getLyrics.py?q=" + url);
    lyricsHttpRequest.send(null);
    
    statusMsg("Request lyrics...");
}

function listRequest()
{
	currentSearchingIndex = -1;
	
	randomQueue = [];
	
	var listType = document.getElementById("list_type2");
	
	if ( listType == null )
	{
		statusMsg("list_type is null");
		return;
	}
	
	/// url 에서 list id 가 있으면 해당 list 를 로딩한다.
	if ( getMylist().length > 0 )
	{
		requestMyList(getMylist());
		return;
	}

	listRequestType = "hot";
	requestMusicChart(null);
}

function makeNewURL(key, value)
{
    var vars = [], hash;
    
    /// url 중에서 첫번째 '?' 이후만 가져온다.
    var findIndex = window.location.href.indexOf('?');
    
    var params = "";

    if ( findIndex != -1 )
    {
    	params = window.location.href.slice(findIndex + 1);
    }
    
    
    /// GET 변수 중에 # 은 제거한다.
    params = params.replace("#", "");
    
    /// '&' 을 기준으로 split 한다.
    var hashes = params.split('&');
    
    var newURL = "/";

    var bFound = false;
    var bFirstArg = true;

    var args = [];
    
    if ( findIndex != -1 )
    {
        for(var i = 0; i < hashes.length; i++)
        {
        	/// '=' 를 기준으로 key 와 value 를 나눈다.
    	    hash = hashes[i].split('=');
    	    vars.push(hash[0]);
    	    vars[hash[0]] = hash[1];
    	    
    	    if ( hash[0] == key )
    	    {
    	    	if ( value != "" )
    	    	{
    	    		args.push(hash[0] + "=" + value);
    	    	}
    	    	bFound = true;
    	    }
    	    else
    	    {
    	    	args.push(hash[0] + "=" + hash[1]);
    	    }
        }
    }

    if ( bFound == false )
    {
    	args.push(key + "=" + value); 
    }
    
    for ( i=0; i<args.length; ++i )
    {
    	if ( i == 0 )
    	{
    		newURL += "?";
    	}
    	
    	newURL += args[i];
    	
    	if ( i != args.length - 1 )
    	{
    		newURL += "&";
    	}
    }
    return newURL;
}

function onDoubleCacheClick()
{
	var newURL = "";
	
	if ( IsDoubleCacheMode() )
	{
		newURL = makeNewURL("cache", "");
	}
	else
	{
		newURL = makeNewURL("cache", "doublecache");
	}
	location.href = newURL;
}

/// 요청된 값으로 새로운 url 을 만들어 요청
function requestNewList(listID)
{
	var newURL = makeNewURL("mylist", listID);
	
	location.href = newURL;
}

/// 사용자가 입력한 값을 가지고 새로운 url 로 만들어 요청
function requestMylistFromEditbox()
{
	var listValue = document.getElementById("mylist_value");
	
	requestNewList(listValue.value);
}

/// 실제로 목록을 요청하는 함수
function requestMyList(listID)
{
	statusMsg("requestMyList");
	if ( listID == null )
	{
		statusMsg("listValue is null");
		return;
	}
	
	/*if ( listID.length != 23 )
	{
		alert("적절한 구글 문서의 키를 넣어주세요. 도움말을 참고하세요.");
		return;
	}*/
	
	listRequestType = "mylist";
	requestMusicChart(listID);
}

function requestMusicChart(listValue)
{
	musicChartRequest = newXMLHttpRequest();
    
    if ( musicChartRequest == null ) return;
    
    musicChartRequest.onreadystatechange = musicChartRequestHandler;
    
    url = "/getMusicChart.py";
    
    if ( listValue )
    {
    	url += "?q=" + listValue;
    }
    
    musicChartRequest.open("GET", url);
    musicChartRequest.send(null);
    
    statusMsg("Request Music list");
}

function refreshLog()
{
    var logDiv = document.getElementById("log");
	
    if ( logDiv )
    {
        logDiv.innerHTML = strLog;
    }
}

function onMoreBufferClick()
{
	var cb = document.getElementById("more_buffer");
	var bufferInput = document.getElementById("more_buffer_input_span");

	if ( cb == null || bufferInput == null )
	{
		statusMsg("more buffer error");
		return;
	}
	
	if ( cb.checked == true )
	{
		bufferInput.style.visibility = "visible";
	}
	else
	{
		bufferInput.style.visibility = "hidden";
	}
}

function onToggleLog()
{
    bShowLog = !bShowLog;

    var logDiv = document.getElementById("log");

    if ( bShowLog )
    {
		logDiv.style.visibility = 'visible';
		refreshLog();
    }
    else
    {
		logDiv.style.visibility = 'hidden';
		logDiv.innerHTML = "";
    }
}

function makeRandomQueue()
{
	//statusMsg("makeRandomQueue");
	
	/// 랜덤 플레이큐를 채운다.
	for ( i=0; i<artists.length; ++i )
	{
		/// 현재 플레이 중인 index 는 제외한다.
		if ( i != currentPlayingIndex )
		{
			randomQueue.push(i);
		}
	}
	
	/// 섞는다.
	for ( i=0; i<randomQueue.length; ++i )
	{
		a = getRandomIndex(randomQueue.length);
		b = getRandomIndex(randomQueue.length);
		
		c = randomQueue[a];
		randomQueue[a] = randomQueue[b];
		randomQueue[b] = c;
	}
	
	//statusMsg("randomQueue : " + randomQueue);
}

function onRandomClick()
{
	if ( IsRandom() )
	{
		statusMsg("랜덤 재생 on");
		makeRandomQueue();
		
		/// DoubleCache 일 때는 다음곡을 미리 불러놓아야한다.
		if ( IsDoubleCacheMode() )
		{
			nextSongPrepare();
		}
	}
	else
	{
		statusMsg("랜덤 재생 off");
		/// 랜덤 플레이큐를 비운다.
		randomQueue = [];
	}
}


