#include "hud.h"
#include "parsemsg.h"
#include "cl_util.h"
#include "vgui_TeamFortressViewport.h"
#include "vgui_mp3menu.h"
#include <fstream>
#include <algorithm>

extern cvar_t *cl_mp3player;
using namespace std;

int CHudMp3Player::Init(void)
{	m_iError = false;	
	m_iMins = 0;
	m_iSecs = 0;
	
	fstream f;

	string sFileName=gEngfuncs.pfnGetGameDirectory();
	sFileName.append("/mp3/playlist.txt");
	
	f.open(sFileName.c_str(),ios::in);
	if(!f.is_open())
	{
		m_iError = true;
		ConsolePrint("Playlist does not exist\n");
		return 1;
	}
	
	int i = 0;
	while (!f.eof())
	{	char charBuf[255];
		f.getline(charBuf,255);
		string buffer = charBuf;		
		if(f.gcount()>0)
		{	m_pFixedPlaylist.push_back(buffer);
			m_pPlaylist.push_back(buffer);
			i++;
		}
	}
	f.close();
	
	m_pCurrentSong = m_pPlaylist.begin();
	
	//no songs on the playlist
	if(i==0)
	{	m_iError = true;
		ConsolePrint("No songs in the playlist\n");
		return 1;
	}
	
	m_eStatus = MP3_NONE;

	gHUD.AddHudElem(this);
	m_iFlags |= HUD_ACTIVE;
	return 1;
}

// added by Pcjoe, modified by harSens
string CHudMp3Player::GetSongName()
{	// Open file
	ifstream filestr;
	filestr.open(m_pCurrentSong->c_str(),ios::binary);

	if(!filestr.is_open())
	{	//try local filename. BUG: this doesn't work somehow, file gets opened, but nothing gets read
		string sFileName = gEngfuncs.pfnGetGameDirectory();
		sFileName.append("/");
		sFileName.append(*m_pCurrentSong);
		filestr.open(sFileName.c_str(),ios::binary);
		if(!filestr.is_open())
		{	return *m_pCurrentSong;
		}
	}

	// Read + Copy to buffer
	char pBuffer[128];	
	filestr.seekg(ios::end);
	if(filestr.gcount()<=128)
	{	return *m_pCurrentSong;
	}
	else
	{	filestr.seekg(-128,ios::end);	
	}
	filestr.read(pBuffer,128);
	
	/*
	char buffer[255];
	sprintf(buffer,"%d bytes read\n",filestr.gcount());
	ConsolePrint(buffer);
	*/
	
	filestr.close();

	// Validate ID3 tag
	char pTag[3];	
	memcpy(pTag,pBuffer,3);
	
	
	if(memcmp(pBuffer,"TAG",3))
	{	return *m_pCurrentSong;
	}
	
	// Copy info
	char pTitle[31];
	char pArtist[31];	
	memcpy(pTitle,pBuffer+3,30);
	memcpy(pArtist,pBuffer+33,30);
	
	// End strings
	pTitle[30] = '\0';
	pArtist[30] = '\0';

	// Format song name ( Artist - Title )
	string sSongName =  pArtist;
	sSongName.append(" - ");
	sSongName.append(pTitle);
	return sSongName;
}

void CHudMp3Player::Play()
{	if (m_iError)
	{	return;
	}

	//do nothing if already playing
	if (m_eStatus == MP3_PLAY)
	{	return;
	}
	
	//unpause if on pause
	if (m_eStatus==MP3_PAUSE)
	{	/*
		if (m_pStream)
		{	FSOUND_SetPaused(FSOUND_ALL, false);
		}
		*/
		m_eStatus = MP3_PLAY;
		return;
	}	

	//open mp3 file
	//try global name	
	ifstream f;
	string sFileName = *m_pCurrentSong;
		
	f.open(sFileName.c_str());
	if (!f.is_open())
	{	//try local name
		sFileName = gEngfuncs.pfnGetGameDirectory();
		sFileName.append("/");
		sFileName.append(*m_pCurrentSong);
		f.open(sFileName.c_str());
		if (!f.is_open())
		{	//m_iError = true;
			ConsolePrint("Can't playback file:");
			ConsolePrint(sFileName.c_str());
			ConsolePrint("\n");
			
			//forces next mp3
			m_pCurrentSong=m_pPlaylist.erase(m_pCurrentSong);
			if(m_pPlaylist.size()>0)
			{
				gViewPort->m_pMp3Menu->SetSong(GetSongName().c_str());
				Play();
			}
			else
			{
				ConsolePrint("no valid mp3's on the playlist\n");
				m_iError = true;
			}
			return ;
		}
	}
	f.close();

	char buffer[255];
	//filename is always current song name, mp3 play doesn't work with the game dir			
	sprintf(buffer,"mp3 play %s",m_pCurrentSong->c_str());
	gEngfuncs.pfnClientCmd(buffer);
	
	// PLAY STREAM
	/*
	if ((m_iChannel = FSOUND_Stream_Play(FSOUND_FREE, m_pStream)) == -1)
	{	m_iError = true;
		ConsolePrint(FMOD_ErrorString(FSOUND_GetError()));
		FSOUND_Close();
		return ;
	}
	
	//set stereo panning
	FSOUND_SetPan(m_iChannel, FSOUND_STEREOPAN);
	mp3_end=0;	
	*/
	m_eStatus = MP3_PLAY;
}

void CHudMp3Player::Shuffle()
{	gViewPort->m_pMp3Menu->SetMode("shuff");
	m_eMode = MP3MODE_SHUFFLE;
	
	//OMG STL has a function for this :D
	random_shuffle(m_pPlaylist.begin(),m_pPlaylist.end());	
}

void CHudMp3Player::Normal()
{	string sCurrentSong = *m_pCurrentSong;
	gViewPort->m_pMp3Menu->SetMode("norm");
	m_eMode = MP3MODE_NORMAL;
	
	m_pPlaylist.clear();
	
	std::vector <std::string>::iterator iter=m_pFixedPlaylist.begin();
	m_pCurrentSong = iter;
	while (iter!=m_pFixedPlaylist.end())
	{
		m_pPlaylist.push_back(*iter);
		if(*iter==sCurrentSong)
		{	
			m_pCurrentSong = m_pPlaylist.end()-1;
		}
		iter++;
	}
}

void CHudMp3Player::Mode()
{
	if(m_eMode == MP3MODE_NORMAL)
	{	Shuffle();		
	}
	else if(m_eMode == MP3MODE_SHUFFLE)
	{	Normal();		
	}
}

void CHudMp3Player::Pause()
{	/*
	if (!m_pStream) 
		return;
	*/
	if (m_eStatus == MP3_PLAY)
	{	//FSOUND_SetPaused(FSOUND_ALL, true);
		m_eStatus = MP3_PAUSE;
		return;
	}
	if (m_eStatus == MP3_PAUSE)
	{	//FSOUND_SetPaused(FSOUND_ALL, false);
		m_eStatus = MP3_PLAY;
		return;
	}
}

void CHudMp3Player::Stop()
{	gEngfuncs.pfnClientCmd("mp3 stop");
		
	gViewPort->m_pMp3Menu->SetTime(0,0);
	m_iMins = 0;
	m_iSecs = 0;
	m_eStatus = MP3_STOP;
}

void CHudMp3Player::Next()
{	if (m_iError)
	{	return;
	}
	
	int oldstatus = m_eStatus;

	//close old mp3 stream and selects next stream
	Stop();		
	
	m_pCurrentSong++;
	if(m_pCurrentSong == m_pPlaylist.end())
	{	m_pCurrentSong = m_pPlaylist.begin();
	}

	//update songname on mp3 menu
	gViewPort->m_pMp3Menu->SetSong(GetSongName().c_str());

	if (oldstatus==MP3_PLAY)
	{	Play();
	}
}

void CHudMp3Player::Previous()
{	if (m_iError)
	{	return;
	}

	int oldstatus=m_eStatus;
	
	//close playing stream
	Stop();
	
	//determine previous song on the list
	if(m_pCurrentSong == m_pPlaylist.begin())
	{	m_pCurrentSong=m_pPlaylist.end();
	}
	m_pCurrentSong--;
	
	//update songname on mp3 menu
	gViewPort->m_pMp3Menu->SetSong(GetSongName().c_str());

	if (oldstatus==MP3_PLAY)
	{	Play();
	}
}

void CHudMp3Player::Think()
{	//error while playing back mp3
	if (m_iError)
	{	return;
	}
	
	if (cl_mp3player->value != 0.0)
	{	if (m_eStatus==MP3_NONE && m_pPlaylist.size()>0)
		{	LoadStatus();
			//update songname on mp3 menu				
			gViewPort->m_pMp3Menu->SetSong(GetSongName().c_str());
			gViewPort->m_pMp3Menu->SetMode("norm");
		}
			
		if (m_eStatus==MP3_PLAY &&  gViewPort->m_pCurrentMenu == gViewPort->m_pMp3Menu )
		{
			/*
			int iPlayingTime = FSOUND_Stream_GetTime(m_pStream);
			int iSecs = iPlayingTime/1000;
			int iMins = iSecs/60;
			iSecs = iSecs%60;
			if (iMins !=m_iMins || iSecs != m_iSecs)
			{	gViewPort->m_pMp3Menu->SetTime(iMins,iSecs);
				m_iMins = iMins;
				m_iSecs = iSecs;
			}
			*/
		}
		//if mp3 has stopped. restart new one
			/*
			if (mp3_end && m_eStatus==MP3_PLAY)
			{	Next();
			}
			*/				
	}
	//else if (m_fInit)
	//{	DeInit();
	//}	
}

void CHudMp3Player::SaveStatus()
{
	/*
	ofstream f;
	string sFileName=gEngfuncs.pfnGetGameDirectory();
	sFileName.append("/mp3/player.sav");
	
	f.open("c:/temp/player.sav",fstream::binary);
	
	if(!f.is_open())
	{	ConsolePrint("can't open player.sav file for writing");
		return;
	}
	f.write((char*)&m_eMode,sizeof(m_eMode));	
	f.write((char*)&m_eStatus,sizeof(m_eStatus));
	
	f.close();		
	*/
}

void CHudMp3Player::LoadStatus()
{	/*
	ifstream f;
	string sFileName=gEngfuncs.pfnGetGameDirectory();
	sFileName.append("/mp3/player.sav");
	
	f.open(sFileName.c_str(),fstream::binary);
	if(!f.is_open())
	*/
	{	//set defaults
		m_eMode = MP3MODE_NORMAL;		
		Play();		
	}
	/*
	//load mode
	if (!f.eof())
	{	f.read((char*)&m_eMode,sizeof(m_eMode));
		switch (m_eMode)
		{
			case MP3MODE_NONE: 
			case MP3MODE_NORMAL: Normal(); break;
			case MP3MODE_SHUFFLE: Shuffle(); break;
			default: ConsolePrint("Read invalid playing mode\n"); Normal();break;
		};
	}
	else
	{	//set defaults
		Play();
		m_eMode = MP3MODE_NORMAL;
		f.close();
		return;
	}

	//load status
	if(!f.eof())
	{	f.read((char*)&m_eStatus,sizeof(m_eStatus));
		switch (m_eStatus)
		{
			case MP3_NONE: Play(); break;
			case MP3_STOP: Stop(); break;
			case MP3_PLAY: Play(); break;
			case MP3_PAUSE: Play();Pause(); break;
			default: ConsolePrint("Read invalid play status\n"); Play();break;
		};		
	}
	else
	{	Play();
		f.close();
		return;
	}
	f.close();
	*/
}

/*
void CHudMp3Player::DeInit()
{	if (!m_iError)	
	{	SaveStatus();
		if (m_pStream)
		{	Stop();
		}
		//FSOUND_Close();
		m_eStatus=MP3_NONE;
		m_fInit = false;
	}
}
*/