#include "menu_myedittimer.h"
#include "epgsearchcfg.h"
#include "epgsearchcats.h"
#include "timer_thread.h"
#include "menu_dirselect.h"
#include "tools.h"
#include <math.h>

extern const char *AllowedChars;
extern int PluginIndex;

cMenuMyEditTimer::cMenuMyEditTimer(cTimer *Timer, bool New, const cEvent* Event)
:cOsdMenu(tr("Edit timer"), 12)
{
    UserDefDaysOfWeek = 0;
    if (Timer) 
    {
      timer = Timer;
      event = Event;
      firstday = NULL;
      flags = Timer->Flags();
      day = Timer->Day();
#if VDRVERSNUM && VDRVERSNUM >= 10323
      weekdays = Timer->WeekDays();
#else
      firstdaydata = Timer->FirstDay();
#endif

      start = Timer->Start();
      stop = Timer->Stop();
      priority = Timer->Priority();
      lifetime = Timer->Lifetime();
      strn0cpy(file, Timer->File(), sizeof(file));
      channel = Timer->Channel()->Number();
      char* tmp = strrchr(file, '~');
      if (tmp)
      {
	  *tmp = 0;
	  strn0cpy(directory, file,sizeof(directory));
	  strn0cpy(file, tmp+1,sizeof(file));
      }
      else
	  *directory = 0;
      
      addIfConfirmed = New;

      Set();
    }
}

void cMenuMyEditTimer::Set()
{
    int current = Current();
    Clear();

    Add(new cMenuEditBitItem( tr("Active"),       &flags, tfActive));
    Add(new cMenuEditChanItem(tr("Channel"),      &channel));
#if VDRVERSNUM && VDRVERSNUM >= 10323
    Add(new cMenuEditDateItem(tr("Day"),          &day, &weekdays));
#else
    Add(new cMenuEditDayItem( tr("Day"),          &day));
#endif
    Add(new cMenuEditTimeItem(tr("Start"),        &start));
    Add(new cMenuEditTimeItem(tr("Stop"),         &stop));
    Add(new cMenuEditBitItem( tr("VPS"),          &flags, tfVps));
    Add(new cMenuEditIntItem( tr("Priority"),     &priority, 0, MAXPRIORITY));
    Add(new cMenuEditIntItem( tr("Lifetime"),     &lifetime, 0, MAXLIFETIME));
    Add(new cMenuEditStrItem( tr("File"),         file, sizeof(file), tr(FileNameChars)));
    Add(new cMenuEditStrItem( tr("Directory"), directory, MaxFileName, tr(AllowedChars)));
    SetFirstDayItem();
    SetCurrent(Get(current));
    Display();
}

cMenuMyEditTimer::~cMenuMyEditTimer()
{
  if (timer && addIfConfirmed)
     delete timer; // apparently it wasn't confirmed
}

void cMenuMyEditTimer::SetFirstDayItem(void)
{
#if VDRVERSNUM && VDRVERSNUM >= 10323
    if (!firstday && !IsSingleEvent()) 
    {
        Add(firstday = new cMenuEditDateItem(tr("First day"), &day));
	Display();
    }
    else if (firstday && IsSingleEvent()) 
    {
	Del(firstday->Index());
	firstday = NULL;
	Display();
    }
#else
  if (!firstday && !IsSingleEvent()) {
     Add(firstday = new cMenuEditDateItem(tr("First day"), &firstdaydata));
     }
  else if (firstday && IsSingleEvent()) {
     Del(firstday->Index());
     firstday = NULL;
     firstdaydata = 0;
     }
#endif
}

void cMenuMyEditTimer::HandleSubtitle()
{
    const char* ItemText = Get(Current())->Text();
    if (strstr(ItemText, tr("File")) != ItemText)
	return;
    if (InEditMode(ItemText, tr("File"), file))
	return;

    if (!event || (event && !event->ShortText()))
	return;
    char* tmp = strchr(file, '~');
    if (tmp)
    {
	*tmp = 0;
	SetHelp(NULL, NULL, tr("Reset"), tr("With subtitle"));
    }
    else
    {
	strcat(file, "~");
	strcat(file, event->ShortText());
	SetHelp(NULL, NULL, tr("Reset"), tr("Without subtitle"));
    }
    RefreshCurrent();
    Display();
}

bool cMenuMyEditTimer::IsSingleEvent(void) const
{
#if VDRVERSNUM && VDRVERSNUM >= 10323
  return !weekdays;
#else
  return (day & 0x80000000) == 0;
#endif
}

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

  int iOnDirectoryItem = 0;
  int iOnFileItem = 0;
  int iOnDayItem = 1;
  const char* ItemText = Get(Current())->Text();
  if (!HasSubMenu() && ItemText && strlen(ItemText)>0)
  {
      if (strstr(ItemText, tr("Day")) == ItemText)
      {
	  if (!IsSingleEvent())
	  {
	      SetHelp(tr("Edit"));
	      iOnDayItem = 1;
	  }
	  else
	      SetHelp(NULL, NULL, NULL, NULL);
      }
      else if (strstr(ItemText, tr("Directory")) == ItemText)
      {
	  if (!InEditMode(ItemText, tr("Directory"), directory))
	      SetHelp(NULL, NULL, tr("Reset"), tr("Select"));
	  iOnDirectoryItem = 1;
      }
      else if (strstr(ItemText, tr("File")) == ItemText)
      {
	  if (!InEditMode(ItemText, tr("File"), file))
	  {
	      if (event && event->ShortText())
	      {
		  if (strchr(file, '~'))
		      SetHelp(NULL, NULL, tr("Reset"), tr("Without subtitle"));
		  else
		      SetHelp(NULL, NULL, tr("Reset"), tr("With subtitle"));
	      }
	      else
		  SetHelp(NULL, NULL, tr("Reset"), NULL);
	  }
	  iOnFileItem = 1;
      }
      else
	  SetHelp(NULL, NULL, NULL, NULL);
  }

  if ((Key == kYellow) && (iOnDirectoryItem && !InEditMode(ItemText, tr("Directory"), directory) ||
			   iOnFileItem && !InEditMode(ItemText, tr("File"), file)))
  {
      if (iOnDirectoryItem)
	  strcpy(directory, "");
      if (iOnFileItem && event)
	  strn0cpy(file, event->Title(),sizeof(file));
      RefreshCurrent();
      Display();
  }

  if (state == osUnknown) 
  {
      switch (Key) 
      {
	  case kOk:     
	  {
	      cChannel *ch = Channels.GetByNumber(channel);
	      if (!ch)
	      {
		  Skins.Message(mtError, tr("*** Invalid Channel ***"));
		  break;
	      }

	      char* tmpFile = strdup(file);
	      tmpFile = strreplace(tmpFile, ':', '|');
	      char* tmpDir = strdup(directory);
	      tmpDir = strreplace(tmpDir, ':', '|');
	      if (strlen(tmpFile) == 0)
		  tmpFile = strdup(CHANNELNAME(ch));

	      char* tmpSummary = NULL;
	      if (event && event->Description())
	      {
		  tmpSummary = strdup(event->Description());
		  strreplace(tmpSummary, '\n', '|');
	      }
	      else
		  tmpSummary = strdup("");

	      if (timer) 
	      {
		  char* cmdbuf = NULL;
		  if (addIfConfirmed)
		      asprintf(&cmdbuf, "NEWT %d:%d:%s:%04d:%04d:%d:%d:%s%s%s:%s", 
			       flags,
			       ch->Number(),
#if VDRVERSNUM && VDRVERSNUM >= 10323
			       PRINTDAY(day, weekdays),
#else
			       PRINTDAY(day, firstdaydata),
#endif
			       start,
			       stop,
			       priority, 
			       lifetime, 
			       strlen(tmpDir)>0?tmpDir:"",
			       (strlen(tmpDir)>0 && strlen(tmpFile)>0)?"~":"",
			       tmpFile,
			       tmpSummary);
		  else
		      asprintf(&cmdbuf, "MODT %d %d:%d:%s:%04d:%04d:%d:%d:%s%s%s:%s", 
			       timer->Index()+1,
			       flags,
			       ch->Number(),
#if VDRVERSNUM && VDRVERSNUM >= 10323
			       PRINTDAY(day, weekdays),
#else
			       PRINTDAY(day, firstdaydata),
#endif
			       start,
			       stop,
			       priority, 
			       lifetime, 
			       strlen(tmpDir)>0?tmpDir:"",
			       (strlen(tmpDir)>0 && strlen(tmpFile)>0)?"~":"",
			       tmpFile,
			       tmpSummary);

		  cTimerThread timerThread;
		  timerThread.Init(cmdbuf);
		  free(cmdbuf);
		  free(tmpFile);
		  free(tmpDir);
		  free(tmpSummary);

		  addIfConfirmed = false;
	      }
	  }
	  return osBack;
	  case kRed:
	      if (HasSubMenu())
		  return osContinue;
	      else
		  if (iOnDayItem)
#if VDRVERSNUM && VDRVERSNUM >= 10323
		      return AddSubMenu(new cMenuEditDaysOfWeek(&weekdays,1,false));
#else
		      return AddSubMenu(new cMenuEditDaysOfWeek(&day,1,false));
#endif
	      return osContinue;
	      break;
	  case kGreen:
	  case kYellow:
	      return osContinue;
	  case kBlue:   
	      if (HasSubMenu())
		  return osContinue;
	      if (iOnDirectoryItem && !InEditMode(ItemText, tr("Directory"), directory))
		  state = AddSubMenu(new cMenuDirSelect(directory));
	      if (iOnFileItem)
	      {
		  HandleSubtitle();
		  return osContinue;
	      }
	      break;
	  default: break;
      }
  }

  if (Key != kNone && !HasSubMenu())
  {
    if (iOnDirectoryItem && !InEditMode(ItemText, tr("Directory"), directory))		
	ReplaceDirVars();
    SetFirstDayItem();
  }
  return state;
}

void cMenuMyEditTimer::ReplaceDirVars()
{
    if (!strchr(directory,'%') || !event)
	return;
    char* tmpDirectory = strdup(directory);
    // replace ext. EPG variables
    cSearchExtCat* SearchExtCat = SearchExtCats.First();
    while (SearchExtCat) 
    {
	char* tmp = NULL;
	// search the category enclosed in %
	asprintf(&tmp, "%%%s%%", SearchExtCat->name);
	if (strstri(tmpDirectory, tmp))
	{
	    char* value = GetExtEPGValue(event, SearchExtCat);
	    if (value)
	    {
		char* tmp_dir = strdup(tmpDirectory);
		tmp_dir = strreplacei(tmp_dir, tmp, value);
		tmpDirectory = strcpyrealloc(tmpDirectory, tmp_dir);
		free(tmp_dir);
		free(value);
	    }
	}
	free(tmp);
	SearchExtCat = SearchExtCats.Next(SearchExtCat);
    }

    // replace Title and Subtitle vars, and empty file, if Title or Subtitle vars exist
    if (strstri(tmpDirectory, "%Title%") ||
        strstri(tmpDirectory, "%Subtitle%"))
	*file = 0;
    char* tmp_dir = strdup(tmpDirectory);
    tmp_dir = strreplacei(tmp_dir, "%Title%", !isempty(event->Title())?event->Title():"?");
    tmpDirectory = strcpyrealloc(tmpDirectory, tmp_dir);
    free(tmp_dir);
    char* Subtitle = NULL;
    if (!isempty(event->ShortText()))
	Subtitle = strdup(event->ShortText());
    else
	asprintf(&Subtitle, "%s-%s", GETDATESTRING(event), GETTIMESTRING(event));
    tmp_dir = strdup(tmpDirectory);
    tmp_dir = strreplacei(tmp_dir, "%Subtitle%", Subtitle);
    tmpDirectory = strcpyrealloc(tmpDirectory, tmp_dir);
    free(tmp_dir);
    free(Subtitle);

    cChannel *channel = Channels.GetByChannelID(event->ChannelID(), true);
    if (channel)
	tmpDirectory = strreplacei(tmpDirectory, "%channel%", CHANNELNAME(channel));

    strn0cpy(directory, tmpDirectory, sizeof(directory));
    free(tmpDirectory);
    RefreshCurrent();
    // update title too
    Get(Current()-1)->Set();
    Display();
}
 
