#include <string>
#include <algorithm>
#include <vector>
#include <vdr/plugin.h>
#include <vdr/tools.h>
#include "audio_thread.h"
#include "log.h"
#include "tracks.h"
#include "deluxe_config.h"
#include "menu_convert.h"

using namespace std;

void Tokenize(const string& str, vector<string>& tokens, const string& delimiters = " ");

// priority for background thread
#define AUDIO_NICE 19

cConvertToAudioThread *cConvertToAudioThread::m_Instance = NULL;
cRecording* cConvertToAudioThread::recording = NULL;
int cConvertToAudioThread::progress = 0;

cConvertToAudioThread::cConvertToAudioThread(cRecording* Recording,  bool CutAfterConversion)
   : cThread("deluxe: convert to audio")
{
   recording = Recording;
   cutafterconversion = CutAfterConversion;
}

cConvertToAudioThread::~cConvertToAudioThread() {
    Stop();
}

void cConvertToAudioThread::Init(cRecording* Recording, bool CutAfterConversion) 
{
    if (m_Instance == NULL) {
	m_Instance = new cConvertToAudioThread(Recording, CutAfterConversion);
	m_Instance->Start();
    }
}

void cConvertToAudioThread::Exit(void) {
    if (m_Instance != NULL) {
	m_Instance->Stop();
	DELETENULL(m_Instance);
    }
}

void cConvertToAudioThread::Stop(void) 
{
    Cancel();
}

void cConvertToAudioThread::Action(void) 
{
    cCondWait::SleepMs(5);
    SetPriority(AUDIO_NICE);
    
    Skins.QueueMessage(mtInfo, tr("Deluxe audio conversion started!"));
   
    cMarks marks;
    marks.Load(recording->FileName());

    if (marks.Count() == 0)
	return;

    cMarks marksall;
    cMark* m;
    for (m = marks.First(); m; m = marks.Next(m))
    {
	cMark* mtemp = marksall.Add(m->position);
	if (m->comment)
	    mtemp->comment = strdup(m->comment);
    }
    marksall.Sort();

    string strMarksFilename = string(recording->FileName()) + "/marks.vdr";
    remove(strMarksFilename.c_str());
    marks.Load(recording->FileName());

    cIndexFile index(recording->FileName(), false);
    progress = 0;
    for (m = marksall.First(); m; m = marksall.Next(m))
    {
	cMark *markStart = m;
	cMark *markStop = m = marksall.Next(m);
	cMark* markStartTemp = marks.Add(markStart->position);
	cMark* markStopTemp = marks.Add(markStop->position);
	marks.Save();
	
	string trackinfo = "";
	if (markStart->comment)
	    trackinfo = markStart->comment;
	vector<string> tokens;
	Tokenize(trackinfo, tokens, "|");	
	if (tokens.size() < 3) continue;
	
	string artist = tokens[0];
	string title = tokens[1];
	string year = tokens[2];

	LogFile.Log(1, "converting to mp3: %s", title.c_str());
	string script = DeluxeConfig.audioFormat == 0? "deluxe2mp3.sh" : "deluxe2ogg.sh";

	string cmd = script + 
	    " \"" + recording->FileName() +
	    "\" \"" + title + 
	    "\" \"" + artist + 
	    "\" \"" + year + "\"";

	SystemExec(cmd.c_str());

	progress = (m->Index()+1)*100/marksall.Count();

	if (markStartTemp) marks.Del(markStartTemp);
	if (markStopTemp) marks.Del(markStopTemp);
	marks.Save();
    }
    
    // restore the old marks
    remove(strMarksFilename.c_str());
    marks.Load(recording->FileName());
    for (m = marksall.First(); m; m = marksall.Next(m))
    {
	cMark* mtemp = marks.Add(m->position);
	if (m->comment)
	    mtemp->comment = strdup(m->comment);
    }
    marks.Save();

    Tracks.SetConverted(recording);

    if (cutafterconversion)
       cMenuConvert::Cut(recording);
    else
       Skins.QueueMessage(mtInfo, tr("Deluxe audio conversion finished!"));
 
    m_Instance = NULL;
}
