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

extern int PluginIndex;

cMenuMyEditTimer::cMenuMyEditTimer(cTimer *Timer, bool New, const cEvent* Event, const cChannel* forcechannel)
:cOsdMenu(tr("Edit timer"), 14)
{
    strcpy(file, "");
    strcpy(directory, "");
    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();
	strcpy(file, Timer->File());
	channel = Timer->Channel()->Number();
	if (forcechannel)
	    channel = forcechannel->Number();
	SplitFile();
	
	addIfConfirmed = New;
	Set();
	SetHelp(addIfConfirmed?NULL:tr("Button$Delete"), NULL, NULL, NULL);
    }
}

void cMenuMyEditTimer::SplitFile()
{
    char* tmp = strrchr(file, '~');
    if (tmp) // split file in real file and directory
    {
	if (event && !isempty(event->ShortText())) 
	{
	    char* eventFile = NULL;
	    asprintf(&eventFile, "%s~%s", event->Title(), event->ShortText());
	    char* tmp2 = strstr(file, eventFile); 
	    free(eventFile);
	    if (tmp2) // file contains title and subtitle
	    {
		if (tmp2 > file)
		{
		    *(tmp2-1) = 0;
		    strcpy(directory, file);
		    strcpy(file, tmp2);
		}
		else
		    *directory = 0;
	    }
	    else
	    {
		*tmp = 0;
		strcpy(directory, file);
		strcpy(file, tmp+1);
	    }
	}
	else
	{
	    *tmp = 0;
	    strcpy(directory, file);
	    strcpy(file, tmp+1);
	}
    }
    else
	*directory = 0;
}

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, MaxFileName, tr(FileNameChars)));
    Add(new cMenuEditStrItem( tr("Directory"), directory, MaxFileName, tr(AllowedChars)));

    int deviceNr = gl_recStatusMonitor->TimerRecDevice(timer);
    if (deviceNr > 0)
    {
	cOsdItem* pInfoItem = new cOsdItem("");
	pInfoItem->SetSelectable(false);
	Add(pInfoItem);
	char* info = NULL;
	asprintf(&info, "%s: %d/%d", tr("recording with device"), deviceNr, cDevice::NumDevices());
	pInfoItem = new cOsdItem(info);
	free(info);
	pInfoItem->SetSelectable(false);
	Add(pInfoItem);
    }


    SetFirstDayItem();
    if (current > -1)
    {
	SetCurrent(Get(current));
        RefreshCurrent();
    }
    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(addIfConfirmed?NULL:tr("Button$Delete"), NULL, tr("Button$Reset"), tr("Button$With subtitle"));
    }
    else
    {
	strcat(file, "~");
	strcat(file, event->ShortText());
	SetHelp(addIfConfirmed?NULL:tr("Button$Delete"), NULL, tr("Button$Reset"), tr("Button$Without subtitle"));
    }
    RefreshCurrent();
    Display();
}

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

char* cMenuMyEditTimer::SummaryExtended(const cEvent* pEvent)
{
#if VDRVERSNUM && VDRVERSNUM <= 10343
    if (!pEvent)
	return NULL;
    char* addSummaryHeader = NULL;
    const char* title = pEvent->Title();
    const char* subtitle = pEvent->ShortText();
    asprintf(&addSummaryHeader, "%s\n%s%s%s", 
	     title?title:"", 
	     subtitle?tr("Subtitle"):"", subtitle?": ":"", subtitle?subtitle:"");
    char* addSummaryFooter = NULL;
    asprintf(&addSummaryFooter, "%s: %d - %s", 
	     tr("Channel"), channel, CHANNELNAME(Channels.GetByNumber(channel)));

    // already there?
    if (pEvent->Description() && strstr(pEvent->Description(), addSummaryHeader) && 
	strstr(pEvent->Description(), addSummaryFooter))
    {
	free(addSummaryHeader);
	free(addSummaryFooter);
	return strdup(pEvent->Description());
    }
    else
    {
	char* tmpSummary = NULL;
	asprintf(&tmpSummary, "%s\n\n%s\n%s", 
		 addSummaryHeader,
		 pEvent->Description()?pEvent->Description():"", 
		 addSummaryFooter);
	free(addSummaryHeader);
	free(addSummaryFooter);
	return tmpSummary;
    }
#else
    return NULL;
#endif
}

eOSState cMenuMyEditTimer::DeleteTimer()
{
    // Check if this timer is active:
    if (timer) {
	if (Interface->Confirm(tr("Delete timer?"))) {
	    if (timer->Recording()) {
		if (Interface->Confirm(tr("Timer still recording - really delete?"))) {
		    timer->Skip();
		    cRecordControls::Process(time(NULL));
		}
		else
		    return osContinue;
	    }
#if VDRVERSNUM && VDRVERSNUM >= 10323
	    isyslog("deleting timer %s", *timer->ToDescr());
#else
	    isyslog("deleting timer %d", timer->Index()+1);
#endif

	    Timers.Del(timer);
	    cOsdMenu::Del(Current());
#if VDRVERSNUM && VDRVERSNUM >= 10315
	    Timers.SetModified();
#endif
	    Display();
	    return osBack;
        }
    }
    return osContinue;
}

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

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

#if VDRVERSNUM && VDRVERSNUM <= 10343
	      char* tmpSummary = SummaryExtended(event);
	      strreplace(tmpSummary, '\n', '|');
#else
	      char* tmpSummary = NULL;
	      if (timer && timer->Aux())
		  tmpSummary = strdup(timer->Aux());
#endif
	      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?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?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
		  else
		      return DeleteTimer();
	      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 (strcasestr(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 (strcasestr(tmpDirectory, "%Title%") ||
        strcasestr(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
    if (Current() > 0)
	Get(Current()-1)->Set();
    Display();
}
 
