#include <string>
#include <algorithm>
#include <vector>
#include "menu_convert.h"
#include "cal-service.h"
#include "deluxe_config.h"
#include "audio_thread.h"

using namespace std;

string ReplaceAll(const string& input, const string& what, const string& with);

void Tokenize(const string& str,
                      vector<string>& tokens,
                      const string& delimiters = " ")
{
    // Skip delimiters at beginning.
    string::size_type lastPos = str.find_first_not_of(delimiters, 0);
    // Find first "non-delimiter".
    string::size_type pos     = str.find_first_of(delimiters, lastPos);

    while (string::npos != pos || string::npos != lastPos)
    {
        // Found a token, add it to the vector.
        tokens.push_back(str.substr(lastPos, pos - lastPos));
        // Skip delimiters.  Note the "not_of"
        lastPos = str.find_first_not_of(delimiters, pos);
        // Find next "non-delimiter"
        pos = str.find_first_of(delimiters, lastPos);
    }
}

// --- cMenuConvert ---------------------------------------------------------

cMenuConvert::cMenuConvert(cRecording* Recording)
:cOsdMenu(tr("Convert deluxe recording"))
{
    SetHasHotkeys();
    
    recording = Recording;

    if (Cutalot())
       Add(new cOsdItem(hk(tr("Create video clips"))));
    Add(new cOsdItem(hk(tr("Create audio clips"))));
    if (Cutalot())
       Add(new cOsdItem(hk(tr("Create audio and video clips"))));

    SetHelp(tr("Button$Start"), NULL, NULL, NULL); 
}

cPlugin* cMenuConvert::Cutalot()
{
    return cPluginManager::GetPlugin("cutalot");
}

string cMenuConvert::FormatMark(string trackinfo)
{
    if (trackinfo == "") return "";
    // already formatted?
    if (trackinfo.find("|") == string::npos) return trackinfo;

    vector<string> tokens;
    Tokenize(trackinfo, tokens, "|");

    if (tokens.size() < 3) return "";

    string formatted = DeluxeConfig.format;
    formatted = ReplaceAll(formatted, "%artist%", tokens[0]);
    formatted = ReplaceAll(formatted, "%title%", tokens[1]);
    formatted = ReplaceAll(formatted, "%year%", tokens[2]);
    return formatted;
}

eOSState cMenuConvert::Cut(cRecording* Recording)
{
    cPlugin* cutalot = Cutalot();
    if (!cutalot) return osContinue;

    if (!Recording) return osContinue;

    cMarks marks;
    marks.Load(Recording->FileName());
    for(cMark* mark = marks.First(); mark; mark = marks.Next(mark))
    {
       char* markcomment = mark->comment;
       if (markcomment)
       {
          string newcomment = FormatMark(markcomment);
          mark->comment = strdup(newcomment.c_str());
          free(markcomment);
       }
    }
    marks.Save();

    Cutalot_MultiCut_v1_0* cal = new Cutalot_MultiCut_v1_0;
    cal->recordingName = strdup(Recording->FileName());

    if (cutalot->Service("Cutalot-MultiCut-v1.0", cal))
    {
       if (cal->message)
          Skins.Message(mtError, cal->message);
       else
          Tracks.SetConverted(Recording);
    }
    else
       Skins.Message(mtError, "Cut-a-lot does not support this service!");
    delete cal;
    return osEnd;
}

eOSState cMenuConvert::ConvertToAudio()
{
    if (cConvertToAudioThread::m_Instance)
       cConvertToAudioThread::Exit();
    else
       cConvertToAudioThread::Init(recording, false);
    return osEnd;
}

eOSState cMenuConvert::ConvertToVideoAudio()
{
    if (cConvertToAudioThread::m_Instance)
       cConvertToAudioThread::Exit();
    else
       cConvertToAudioThread::Init(recording, true);
    return osEnd;
}

eOSState cMenuConvert::Execute(void)
{
  int current = Current();
  if (!Cutalot()) current++;

  if (current < 3)
  {
     if (current == 0)
     	return Cut(recording);
     if (current == 1)
        return ConvertToAudio(); 
     if (current == 2)
        return ConvertToVideoAudio(); 
  }
  return osContinue;
}

eOSState cMenuConvert::ProcessKey(eKeys Key)
{
    eOSState state = cOsdMenu::ProcessKey(Key);

    if (state == osUnknown) {
	switch (Key) {
	    case kRed:
	    case kOk:  
		state = Execute();
		break;
	    default:   break;
	}
    }
    return state;
}
