// SmartRipperInfoFile.cpp: implementation of the SmartRipperInfoFile class.
//
//////////////////////////////////////////////////////////////////////

#include "SmartRipperInfoFile.h"
#include "conf.h"

#include <fstream>
#include <sstream>
#include <strstream>
#include <list>
#include <iostream>
#include "../Error.h"

using namespace std;
//#undef DVD_T
//#define DVD_T(A)

static bool FindValue(istream & p_Source,const char * p_Key,string & p_Result,char delim = 0,bool keeponsearching = true)
{
	char l_Buffer[128];
	p_Source.getline(l_Buffer,128);
	DVD_T("read : " << l_Buffer)
	if (!p_Source)
		throw MyError("Error parsing info file when searching for %s",p_Key);
	if (strlen(p_Key) > strlen(l_Buffer)+1)	//	no need to try and find the key ...
	{
		if (keeponsearching)
			return FindValue(p_Source,p_Key,p_Result);
		else
			return false;
	}
	string l_Line(l_Buffer);
	string::size_type l_Pos = l_Line.find(p_Key);
	if (l_Pos == string::npos)//	not found : searching next line
	{
		if (keeponsearching)
			return FindValue(p_Source,p_Key,p_Result);
		else
			return false;
	}
	string::size_type l_OffSet = l_Pos + strlen(p_Key) ;
	string::size_type l_EndPos = string::npos;
	if (delim)
		l_EndPos = l_Line.find(delim,l_Pos);
	p_Result.assign(l_Line,l_OffSet, ((l_EndPos == string::npos) ? l_Line.size() : l_EndPos)- l_OffSet);
	DVD_T("used : " << p_Result.c_str() );
	return true;
}
static void FindValues(istream & p_Source,const char * p_Key,list<string> & p_Result)
{
	p_Result.clear();
	string l_tmp;
	DVD_T("searching for list of : "<<p_Key)
	FindValue(p_Source,p_Key,l_tmp);//seek to the first one
	p_Result.push_back(l_tmp);
	while (FindValue(p_Source,p_Key,l_tmp,0,false))//	get the others
		p_Result.push_back(l_tmp);
	DVD_T("number of values found :"<< p_Result.size() )
}
SmartRipperInfoFile::SmartRipperInfoFile(const char * p_File)
{
	Init(p_File);
}

SmartRipperInfoFile::~SmartRipperInfoFile(void)
{}
void SmartRipperInfoFile::Init(const char *  p_File)
{
	m_Files.clear();
	m_Name = "";
	m_Frames = 0;
	m_Chapters.clear();
	m_VideoStream = "";
	m_AudioStreams.clear();

	const char * ext = p_File + strlen(p_File) - 4;
	if (_stricmp(ext,".txt")==0)
	{
		ifstream l_Infofile(p_File);
		FindValue(l_Infofile,"Name: ",m_Name);

		string l_Frames;
		FindValue(l_Infofile,"Frames:",l_Frames);
		istringstream l_Conv(l_Frames);
		l_Conv >> m_Frames;

		list<string> l_Streams;
		FindValues(l_Infofile,"Stream[",l_Streams);
		list<string>::iterator i;
		for(i = l_Streams.begin(); i != l_Streams.end();)
		{
			//	do not take into account empty streams 
			if (((*i).find("0=")) != string::npos)
			{
				l_Streams.erase(i);
				i = l_Streams.begin();
			}
			else
				i++;
		}
		i = l_Streams.begin();//	assuming video is the first stream
		istringstream l_video(*i++);
		FindValue(l_video,"Video ",m_VideoStream,']');
		for(; i != l_Streams.end();i++)
		{
			istringstream l_audio(*i);
			string audio;
			istringstream l_tmp(*i);
			string streamnumber;
			unsigned int nb = 0;
			if (FindValue(l_tmp,"[[0x",streamnumber,']',false))
			{
				istringstream s(streamnumber);
				s >> hex >> nb;
				nb -= 0x80;
			}
			if (FindValue(l_audio,"Audio ",audio,']',false))
			{
				string::size_type l_Pos = audio.find(" ]");
				string::size_type l_Pos2 = audio.rfind("[");
				if ((l_Pos != string::npos) && (l_Pos2 != string::npos) && (l_Pos < l_Pos2))
				{
					string bitrate = audio.substr(l_Pos2,audio.size()-l_Pos2);
					audio = audio.substr(0,l_Pos);
					audio += bitrate;
				}
				m_AudioStreams.push_back(audio);
				m_AudioTracks.push_back(nb);
			}
		}

		// to do : chapters
		string dummy;
		FindValue(l_Infofile,"* VOBFile Out",dummy);//only for seeking
		char buffer[512];
		l_Infofile.getline(buffer,512).getline(buffer,512);//	skip 2 lines
		string l_vob = " ";// != ""
		while (l_vob != "")
		{
			l_Infofile.getline(buffer,512);
			l_vob = buffer;
			if (l_vob != "")
			{
				m_Files.push_back(l_vob);
				DVD_T("added file : " << buffer );
			}
		}
	}
	else if (_stricmp(ext,".vob")==0)
	{
		m_Name = p_File;
		m_VideoStream = "unknown video stream";
		m_AudioStreams.push_back(string("unknown audio stream"));
		m_AudioTracks.push_back(0);// let's suppose it's 0x80
		m_Files.push_back(m_Name);
	}
	else
		throw MyError("File extension should be .txt or .vob for MPEG2");
}

