/* 
 * menu_main.c: A plugin for the Video Disk Recorder
 *
 * See the README file for copyright information and how to reach the author.
 *
 * $Id$
 */
#include "menu_main.h"
#include "menu_whatson.h"
#include "menu_myedittimer.h"
#include "epgsearchext.h"
#include "menu_event.h"
#include "menu_searchresults.h"
#include "menu_commands.h"
#include "epgsearchcfg.h"
#include "tools.h"

int toggleKeys=0;

cMenuScheduleItem::cMenuScheduleItem(const cEvent *Event)
{
  event = Event;
  char *buffer = NULL;
  int TimerMatch;
  char t = Timers.GetMatch(Event, &TimerMatch) ? (TimerMatch == tmFull) ? 'T' : 't' : ' ';
  char v = event->Vps() && (event->Vps() - event->StartTime()) ? 'V' : ' ';
  char r = event->IsRunning() ? '*' : ' ';
  asprintf(&buffer, "%.*s\t%s\t%c%c%c\t%s", 6, GETDATESTRING(event), GETTIMESTRING(event), t, v, r, event->Title());
  SetText(buffer, false);

}

// --- cMenuSearchMain ---------------------------------------------------------


cMenuSearchMain::cMenuSearchMain(void)
:cOsdMenu("", 10, 7, 4)
{
    otherChannel = 0;
    toggleKeys = 0;
    shiftTime = 0;
    InWhatsOnMenu = false;
    cChannel *channel = Channels.GetByNumber(cDevice::CurrentChannel());
    if (channel) {
	cMenuWhatsOnSearch::SetCurrentChannel(channel->Number());
	schedules = cSchedules::Schedules(schedulesLock);
	PrepareSchedule(channel);
	SetHelpKeys();
	cMenuWhatsOnSearch::currentShowMode = showNow;
    }
    if (EPGSearchConfig.StartMenu == 1)
    {
	InWhatsOnMenu = true;
	AddSubMenu(new cMenuWhatsOnSearch(schedules, cDevice::CurrentChannel()));
    }
}

cMenuSearchMain::~cMenuSearchMain()
{
    cMenuWhatsOnSearch::ScheduleEvent(); // makes sure any posted data is cleared
}

void cMenuSearchMain::PrepareSchedule(cChannel *Channel)
{
    Clear();
    char *buffer = NULL;
    asprintf(&buffer, tr("Schedule - %s"), Channel->Name());
    SetTitle(buffer);
    free(buffer);

    if (schedules) {
	const cSchedule *Schedule = schedules->GetSchedule(Channel->GetChannelID());
	if (Schedule) 
	{
	    currentChannel = Channel->Number();
	    const cEvent *PresentEvent = Schedule->GetPresentEvent(currentChannel == cDevice::CurrentChannel());
	    time_t now;
	    if (shiftTime == 0)
		now = time(NULL) - Setup.EPGLinger * 60;
	    else
		now = time(NULL) + shiftTime * 60;
	    for (const cEvent *Event = Schedule->Events()->First(); Event; Event = Schedule->Events()->Next(Event)) {
		if (Event->EndTime() > now || (shiftTime==0 && Event == PresentEvent))
		    Add(new cMenuScheduleItem(Event), Event == PresentEvent);
            }
        }
    }
    if (shiftTime)
    {
	char *buffer = NULL;
	asprintf(&buffer, tr("%s (%s%dh %dm)"), Channel->Name(), shiftTime>0?"+":"", shiftTime/60, shiftTime%60);
	SetTitle(buffer);
	free(buffer);
    }
}

eOSState cMenuSearchMain::Record(void)
{
  cMenuScheduleItem *item = (cMenuScheduleItem *)Get(Current());
  if (item) {
     cTimer *timer = new cTimer(item->event);
     cTimer *t = Timers.GetTimer(timer);
     if (t) {
        delete timer;
        timer = t;
        }
     return AddSubMenu(new cMenuMyEditTimer(timer, !t, item->event));
     }
  return osContinue;
}

eOSState cMenuSearchMain::Switch(void)
{
  cMenuWhatsOnSearchItem *item = (cMenuWhatsOnSearchItem *)Get(Current());
  if (item) {
     cChannel *channel = Channels.GetByChannelID(item->event->ChannelID(), true);
     if (channel && cDevice::PrimaryDevice()->SwitchChannel(channel, true))
        return osEnd;
     }
  Skins.Message(mtInfo, tr("Can't switch channel!")); 
  return osContinue;
}

eOSState cMenuSearchMain::ExtendedSearch(void)
{
    return AddSubMenu(new cMenuEPGSearchExt());
}
 
eOSState cMenuSearchMain::Commands(eKeys Key)
{
  if (HasSubMenu() || Count() == 0)
     return osContinue;
  cMenuWhatsOnSearchItem *mi = (cMenuWhatsOnSearchItem *)Get(Current());
  if (mi && mi->event) {
        cMenuSearchCommands *menu;
        eOSState state = AddSubMenu(menu = new cMenuSearchCommands(tr("EPG Commands"), mi->event, true));
        if (Key != kNone)
           state = menu->ProcessKey(Key);
        return state;
     }
  return osContinue;
}

void cMenuSearchMain::SetHelpKeys()
{
    if (toggleKeys==0)
	SetHelp((EPGSearchConfig.redkeymode==0?tr("Record"):tr("Button$Commands")), tr("Now"), tr("Next"), EPGSearchConfig.bluekeymode==0?tr("Switch"):tr("Button$Search"));
    else
    {	
	const char* szGreenToggled = CHANNELNAME(Channels.GetByNumber(currentChannel-1,-1));
	const char* szYellowToggled = CHANNELNAME(Channels.GetByNumber(currentChannel+1,1));
	    
	SetHelp((EPGSearchConfig.redkeymode==1?tr("Record"):tr("Button$Commands")), (EPGSearchConfig.toggleGreenYellow==0?tr("Now"):szGreenToggled), (EPGSearchConfig.toggleGreenYellow==0?tr("Next"):szYellowToggled), EPGSearchConfig.bluekeymode==1?tr("Switch"):tr("Button$Search"));
    }
}

eOSState cMenuSearchMain::Shift(int iMinutes)
{
    shiftTime += iMinutes;
    cChannel *channel = Channels.GetByNumber(cDevice::CurrentChannel());
    PrepareSchedule(channel);
    Display();
    return osContinue;
}

eOSState cMenuSearchMain::ProcessKey(eKeys Key)
{
    if (!HasSubMenu() && Key == kBack)
	return osEnd;

  eOSState state = cOsdMenu::ProcessKey(Key);

  if (state == osUnknown) {
     switch (Key) {
	 case kFastRew:
	     if (HasSubMenu() && !InWhatsOnMenu)
	     {
		 if (Count())
		 {
		     CursorUp();
		     return AddSubMenu(new cMenuEventSearch(((cMenuScheduleItem *)Get(Current()))->event, otherChannel));
		 }
	     }
	     else
		 return Shift(-EPGSearchConfig.timeShiftValue);
	 case kFastFwd:
	     if (HasSubMenu() && !InWhatsOnMenu)
	     {
		 if (Count())
		 {
		     CursorDown();
		     return AddSubMenu(new cMenuEventSearch(((cMenuScheduleItem *)Get(Current()))->event, otherChannel));
		 }
	     }
	     else
		 return Shift(EPGSearchConfig.timeShiftValue);
	 case kRecord:
	 case kRed:
	     if(HasSubMenu()) {
		 state = Record();
		 break;
	     } 
	     if (Count())
	     {
		 if (EPGSearchConfig.redkeymode==toggleKeys)
		     state = Record();
		 else
		 {
		     cMenuWhatsOnSearchItem *mi = (cMenuWhatsOnSearchItem *)Get(Current());
		     if (mi) {
			 if (mi->event) {
			     return AddSubMenu(new cMenuSearchCommands(tr("EPG Commands"),mi->event));
			 }
		     }
		 }
	     }
	     break;
	 case k0:
	     if(!HasSubMenu()) 
	     {
		 toggleKeys = 1 - toggleKeys;
		 SetHelpKeys();
	     }
	     state = osContinue;
	     break;
	 case k1...k9: 
	     if (!HasSubMenu())
		 return Commands(Key);
	     else
		 state = osContinue;
	     break;
	 case kGreen:  
	     if (schedules) 
	     {
		 if (HasSubMenu() && !InWhatsOnMenu)
		 {
		 esyslog("has submenu");

		     if (Count())
		     {
			 CursorUp();
			 return AddSubMenu(new cMenuEventSearch(((cMenuScheduleItem *)Get(Current()))->event, otherChannel));
		     }
		 }
		 else if (toggleKeys == 0 || (toggleKeys == 1 && EPGSearchConfig.toggleGreenYellow == 0))
		 {
		     int ChannelNr = cDevice::CurrentChannel();
		     if (Count()) {
			 cMenuScheduleItem* Item = (cMenuScheduleItem *)Get(Current());
			 if (Item && Item->event)
			 {
			     cChannel *channel = Channels.GetByChannelID(Item->event->ChannelID(), true);
			     if (channel)
				 ChannelNr = channel->Number();
			 }
		     }
		     InWhatsOnMenu = true;
		     return AddSubMenu(new cMenuWhatsOnSearch(schedules, ChannelNr));
		 }
		 else
		 {
		     cChannel *channel = Channels.GetByNumber(currentChannel-1,-1);
		     
		     if (channel) {
			 PrepareSchedule(channel);
			 if (channel->Number() != cDevice::CurrentChannel()) {
			     otherChannel = channel->Number();
			 }
			 Display();
		     }
		     SetHelpKeys();
		     return osContinue;
		 }
	     }
	 case kYellow: 
	     if (schedules)
	     {
		 if (HasSubMenu())
		 {
		     if (Count())
		     {
			 CursorDown();
			 return AddSubMenu(new cMenuEventSearch(((cMenuScheduleItem *)Get(Current()))->event, otherChannel));
		     }
		 }
		 else if (toggleKeys == 0 || (toggleKeys == 1 && EPGSearchConfig.toggleGreenYellow == 0))
		 {
		     cMenuWhatsOnSearch::currentShowMode = showNext;
		     InWhatsOnMenu = true;
		     return AddSubMenu(new cMenuWhatsOnSearch(schedules, cMenuWhatsOnSearch::CurrentChannel()));
		 }
		 else
		 {
		     cChannel *channel = Channels.GetByNumber(currentChannel+1,1);
		     if (channel) {
			 PrepareSchedule(channel);
			 if (channel->Number() != cDevice::CurrentChannel()) {
			     otherChannel = channel->Number();
			 }
			 Display();
		     }
		     SetHelpKeys();
		     return osContinue;
		 }
	     }
	     break;
	 case kBlue:
	     if (HasSubMenu())
		 return Switch();
	     if (EPGSearchConfig.bluekeymode==toggleKeys)
		 return Switch();
	     else
		 return ExtendedSearch();
	     break;
       case kOk: 
	   if (Count())
	       return AddSubMenu(new cMenuEventSearch(((cMenuScheduleItem *)Get(Current()))->event, otherChannel));
	   break;
	 default:
	     break;
     }
  }
  else if (!HasSubMenu()) {
      const cEvent *ei = cMenuWhatsOnSearch::ScheduleEvent();
      InWhatsOnMenu = false;
      if (ei) {
	  cChannel *channel = Channels.GetByChannelID(ei->ChannelID(), true);
	  if (channel) {
	      PrepareSchedule(channel);
	      if (channel->Number() != cDevice::CurrentChannel()) {
		  otherChannel = channel->Number();
              }
	      Display();
	  }
      }
      SetHelpKeys();
  }
  return state;
}

