#include "services/remotetimers.h"
#include "tools.h"
#include "recmenuview.h"
#include "recmenus.h"

// --- cRecMenuMain  ---------------------------------------------------------
cRecMenuMain::cRecMenuMain(bool epgSearchAvailable, bool timerActive, bool switchTimerActive) {
    eRecMenuState action = rmsInstantRecord;
    if (!timerActive) {
        if (config.instRecFolderMode == eFolderSelect)
            action = rmsInstantRecordFolder;
        AddMenuItem(new cRecMenuItemButton(tr("Instant Record"), action, true, false, false, true));
    } else {
        AddMenuItem(new cRecMenuItemButton(tr("Delete Timer"), rmsDeleteTimer, true, false, false, true));
        AddMenuItem(new cRecMenuItemButton(tr("Edit Timer"), rmsEditTimer, false, false, false, true));
    }

    AddMenuItem(new cRecMenuItemButton(tr("Timer Timeline"), rmsTimeline, false, false, false, true));

    if (epgSearchAvailable) {
        AddMenuItem(new cRecMenuItemButton(tr("Create Search Timer"), rmsSearchTimer, false, false, false, true));
        AddMenuItem(new cRecMenuItemButton(tr("Search Timers"), rmsSearchTimers, false, false, false, true));
    }

    if (config.instRecFolderMode == eFolderSelect)
        action = rmsSeriesTimerFolder;
    else
        action = rmsSeriesTimer;
    AddMenuItem(new cRecMenuItemButton(tr("Create Series Timer"), action, false, false, false, true));

    if (epgSearchAvailable) {
        if (!switchTimerActive) {
            AddMenuItem(new cRecMenuItemButton(tr("Create Switch Timer"), rmsSwitchTimer, false, false, false, true));
        } else {
            AddMenuItem(new cRecMenuItemButton(tr("Delete Switch Timer"), rmsSwitchTimerDelete, false, false, false, true));
        }
        AddMenuItem(new cRecMenuItemButton(tr("Search"), rmsSearch, false, false, false, true));
    }

    if (epgSearchAvailable) {
        AddMenuItem(new cRecMenuItemButton(tr("Check for Timer Conflicts"), rmsTimerConflicts, false, false, false, true));
    }

    AddMenuItem(new cRecMenuItemButton(tr("Search in Recordings"), rmsRecordingSearch, false, false, false, true));

    int menuWidth = CalculateOptimalWidth() + 4 * border;
    SetWidthPixel(menuWidth);
            
    CalculateHeight();
    CreatePixmap();
    Arrange();
};

/******************************************************************************************
*   Instant Timer Menus
******************************************************************************************/

// --- cRecMenuAskFolder  ---------------------------------------------------------
cRecMenuAskFolder::cRecMenuAskFolder(const cEvent *event, eRecMenuState nextAction) {
    SetWidthPercent(80);
    NextAction = nextAction;
    cString message = tr("Set Folder for");
    cString headerText = cString::sprintf("%s\n\"%s\"", *message, event->Title());
    cRecMenuItemInfo *infoItem = new cRecMenuItemInfo(*headerText, true);
    infoItem->CalculateHeight(width - 2 * border);
    SetHeader(infoItem);
    
    AddMenuItemInitial(new cRecMenuItemButton(tr("root video folder"), nextAction, true, false, true));
    
    ReadRecordingDirectories(&folders, NULL, "");
    int numFolders = folders.size();
    for (int i=0; i < numFolders; i++) {
        if (!AddMenuItemInitial(new cRecMenuItemButton(folders[i].c_str(), nextAction, false, false, true)))
            break;
    }
    
    CalculateHeight();
    CreatePixmap();
    Arrange();
}

cRecMenuItem *cRecMenuAskFolder::GetMenuItem(int number) { 
    if (number == 0) {
        cRecMenuItem *result = new cRecMenuItemButton(tr("root video folder"), rmsInstantRecord, false, false, true);
        return result;
    } else if ((number > 0) && (number < (int)folders.size() + 1)) {
        cRecMenuItem *result = new cRecMenuItemButton(folders[number-1].c_str(), rmsInstantRecord, false, false, true);
        return result;
    }
    return NULL;
}

int cRecMenuAskFolder::GetTotalNumMenuItems(void) { 
    return folders.size()+1;
}

std::string cRecMenuAskFolder::GetFolder(void) {
    std::string folder = "";
    int folderActive = GetActive();
    if (folderActive > 0 && folderActive < (int)folders.size() + 1)
        folder = folders[folderActive - 1];
    return folder;
}

// --- cRecMenuConfirmTimer  ---------------------------------------------------------
cRecMenuConfirmTimer::cRecMenuConfirmTimer(const cEvent *event, bool timerChanged) {
    SetWidthPercent(50);
#if VDRVERSNUM >= 20301
    LOCK_CHANNELS_READ;
    const cString channelName = Channels->GetByChannelID(event->ChannelID())->Name();
#else
    const cString channelName = Channels.GetByChannelID(event->ChannelID())->Name();
#endif
    bool eventHasTimer = false;
    if (config.useRemoteTimers && pRemoteTimers) {
        RemoteTimers_GetMatch_v1_0 rtMatch;
        rtMatch.event = event;
        pRemoteTimers->Service("RemoteTimers::GetMatch-v1.0", &rtMatch);
        if (rtMatch.timerMatch == tmFull) {
            eventHasTimer = true;                
        }
    } else {
        eventHasTimer = event->HasTimer();
    }
    const cString message = (eventHasTimer) ? (timerChanged) ? tr("Timer changed")
                                                             : tr("Timer created")
                                            : tr("Timer NOT created");
    cString text = cString::sprintf("%s\n%s\n%s %s - %s\n%s", 
                                    *message, 
                                    *channelName,
                                    *event->GetDateString(),
                                    *event->GetTimeString(),
                                    *event->GetEndTimeString(),
                                    event->Title()
                                );
    cRecMenuItemInfo *infoItem = new cRecMenuItemInfo(*text);
    infoItem->CalculateHeight(width - 2 * border);
    AddMenuItem(infoItem);
    AddMenuItem(new cRecMenuItemButton(tr("OK"), rmsClose, true, true));
    CalculateHeight();
    CreatePixmap();
    Arrange();
}

// --- cRecMenuConfirmDeleteTimer  ---------------------------------------------------------
cRecMenuConfirmDeleteTimer::cRecMenuConfirmDeleteTimer(const cEvent *event) {
    SetWidthPercent(50);
#if VDRVERSNUM >= 20301
    LOCK_CHANNELS_READ;
    const cString channelName = Channels->GetByChannelID(event->ChannelID())->Name();
#else
    const cString channelName = Channels.GetByChannelID(event->ChannelID())->Name();
#endif
    cString text = cString::sprintf("%s\n%s\n%s %s - %s\n%s", 
                                    tr("Timer deleted"), 
                                    *channelName,
                                    *event->GetDateString(),
                                    *event->GetTimeString(),
                                    *event->GetEndTimeString(),
                                    event->Title()
                                );
    cRecMenuItemInfo *infoItem = new cRecMenuItemInfo(*text);
    infoItem->CalculateHeight(width - 4 * border);
    AddMenuItem(infoItem);
    AddMenuItem(new cRecMenuItemButton(tr("OK"), rmsClose, true, true));
    
    CalculateHeight();
    CreatePixmap();
    Arrange();
}

// --- cRecMenuAskDeleteTimer ---------------------------------------------------------
cRecMenuAskDeleteTimer::cRecMenuAskDeleteTimer(const cEvent *event) {
    SetWidthPercent(50);
#if VDRVERSNUM >= 20301
    LOCK_CHANNELS_READ;
    const cString channelName = Channels->GetByChannelID(event->ChannelID())->Name();
#else
    const cString channelName = Channels.GetByChannelID(event->ChannelID())->Name();
#endif
    cString text = cString::sprintf("%s \"%s, %s\" %s", 
                                    tr("Timer"),
                                    *channelName,
                                    event->Title(),
                                    tr("still recording - really delete?"));
    cRecMenuItemInfo *infoItem = new cRecMenuItemInfo(*text);
    infoItem->CalculateHeight(width - 4 * border);
    AddMenuItem(infoItem);
    AddMenuItem(new cRecMenuItemButtonYesNo(tr("Yes"), tr("No"), rmsDeleteTimerConfirmation, rmsClose, true));
    CalculateHeight();
    CreatePixmap();
    Arrange();
}

// --- cRecMenuTimerConflicts  ---------------------------------------------------------
cRecMenuTimerConflicts::cRecMenuTimerConflicts(cTVGuideTimerConflicts *conflicts) {
    SetWidthPercent(50);

    int numConflicts = (conflicts) ? conflicts->NumConflicts() : 0;
    cString text;
    if (numConflicts == 1) {
        text = cString::sprintf("%s %s %s", tr("One"), tr("Timer Conflict"), tr("detected"));
    } else {
        text = cString::sprintf("%d %s %s", conflicts->NumConflicts(), tr("Timer Conflicts"), tr("detected"));
    }
    cRecMenuItemInfo *infoItem = new cRecMenuItemInfo(*text, true);
    
    for (int i=0; i<numConflicts; i++) {
        cTVGuideTimerConflict *conflict = conflicts->GetConflict(i);
        if (!conflict)
            continue;
        cString dateTime = DayDateTime(conflict->time);
        int numTimers = conflict->timerIDs.size();
        cString textConflict = cString::sprintf("%s: %s (%d %s)", tr("Show conflict"), *dateTime, numTimers, tr("timers involved"));
        bool isActive = (i==0)?true:false;
        AddMenuItem(new cRecMenuItemButton(*textConflict, rmsTimerConflict, isActive));
    }
    
    SetWidthPixel(CalculateOptimalWidth() + 4*border);
    infoItem->CalculateHeight(width - 2 * border);
    SetHeader(infoItem);
    AddMenuItem(new cRecMenuItemButton(tr("Ignore Conflicts"), rmsClose, false));
    
    CalculateHeight();
    CreatePixmap();
    Arrange();
}

int cRecMenuTimerConflicts::GetTimerConflict(void) {
    return GetActive();
}

// --- cRecMenuTimerConflict  ---------------------------------------------------------
cRecMenuTimerConflict::cRecMenuTimerConflict(cTVGuideTimerConflict *conflict) {
    SetWidthPercent(95);
    this->conflict = conflict;
    totalNumMenuItems = (int)conflict->timerIDs.size();

    SetHeader(new cRecMenuItemTimerConflictHeader(conflict->timeStart,
                                                  conflict->timeStop,
                                                  conflict->overlapStart,
                                                  conflict->overlapStop));
    SetFooter(new cRecMenuItemButton(tr("Ignore Conflict"), rmsIgnoreTimerConflict, false, true));
    int i=0;
    for(std::vector<int>::iterator it = conflict->timerIDs.begin(); it != conflict->timerIDs.end(); it++) {
#if VDRVERSNUM >= 20301
        LOCK_TIMERS_READ;
        const cTimer *timer = Timers->GetById(*it + 1);
#else
        const cTimer *timer = Timers.Get(*it);
#endif
        if (timer) {
            if (!AddMenuItemInitial(new cRecMenuItemTimer(  timer,
                                                      rmsTimerConflictShowInfo,
                                                      rmsDeleteTimerConflictMenu, 
                                                      rmsEditTimerConflictMenu,
                                                      rmsSearchRerunsTimerConflictMenu,
                                                      conflict->timeStart, 
                                                      conflict->timeStop, 
                                                      conflict->overlapStart, 
                                                      conflict->overlapStop, 
                                                      (!i)?true:false)
            ))
                break;
            i++;
        }
    }
    CalculateHeight();
    CreatePixmap();
    Arrange();
}
    
cRecMenuItem *cRecMenuTimerConflict::GetMenuItem(int number) { 
    if ((number >= 0) && (number < totalNumMenuItems)) {
#if VDRVERSNUM >= 20301
        LOCK_TIMERS_READ;
        const cTimer *timer = Timers->Get(conflict->timerIDs[number]);
#else
        const cTimer *timer = Timers.Get(conflict->timerIDs[number]);
#endif
        cRecMenuItem *result = new cRecMenuItemTimer( timer,
                                                      rmsTimerConflictShowInfo,
                                                      rmsDeleteTimerConflictMenu, 
                                                      rmsEditTimerConflictMenu,
                                                      rmsSearchRerunsTimerConflictMenu,
                                                      conflict->timeStart, 
                                                      conflict->timeStop, 
                                                      conflict->overlapStart, 
                                                      conflict->overlapStop, 
                                                      false);
        return result;
    }
    return NULL;
}

int cRecMenuTimerConflict::GetTotalNumMenuItems(void) {
    return totalNumMenuItems; 
}

int cRecMenuTimerConflict::GetTimerConflictIndex(void) {
    return GetActive();
}

// --- cRecMenuNoTimerConflict ---------------------------------------------------------
cRecMenuNoTimerConflict::cRecMenuNoTimerConflict(void) {
    SetWidthPercent(50);
    cString text = tr("No Timer Conflicts found");
    cRecMenuItemInfo *infoItem = new cRecMenuItemInfo(*text);
    infoItem->CalculateHeight(width - 4 * border);
    AddMenuItem(infoItem);
    AddMenuItem(new cRecMenuItemButton(tr("Close"), rmsClose, true));
    CalculateHeight();
    CreatePixmap();
    Arrange();
}

// --- cRecMenuRerunResults ---------------------------------------------------------
cRecMenuRerunResults::cRecMenuRerunResults(const cEvent *original, const cEvent **reruns, int numReruns) {
    this->reruns = reruns;
    this->numReruns = numReruns;
    SetWidthPercent(70);
    this->numReruns = numReruns;
    cString message1 = tr("reruns for");
    cString message2 = tr("rerun for");
    cString message3 = tr("found");
    cString infoText = cString::sprintf("%d %s:\n\"%s\" %s", numReruns, (numReruns>1)?(*message1):(*message2), original->Title(), *message3);
    cRecMenuItem *infoItem = new cRecMenuItemInfo(*infoText, true);
    infoItem->CalculateHeight(width - 2 * border);
    SetHeader(infoItem);
    
    cRecMenuItem *button = new cRecMenuItemButton(tr("Ignore reruns"), rmsTimerConflictIgnoreReruns, false);
    SetFooter(button);
    
    if (reruns && (numReruns > 0)) {
        for (int i=0; i<numReruns; i++) {
            if (!AddMenuItemInitial(new cRecMenuItemEvent(reruns[i], rmsSearchShowInfo, rmsTimerConflictRecordRerun, (i==0)?true:false)))
                break;
        }
    }
    CalculateHeight();
    CreatePixmap();
    Arrange();
}

cRecMenuItem *cRecMenuRerunResults::GetMenuItem(int number) {
   if ((number >= 0) && (number < numReruns)) {
        cRecMenuItem *result = new cRecMenuItemEvent(reruns[number], rmsSearchShowInfo, rmsTimerConflictRecordRerun, false);
        return result;
    }
    return NULL;
}

int cRecMenuRerunResults::GetTotalNumMenuItems(void) {
    return numReruns;
}

const cEvent *cRecMenuRerunResults::GetRerunEvent(void) {
    cRecMenuItemEvent *activeItem = dynamic_cast<cRecMenuItemEvent*>(GetActiveMenuItem());
    return activeItem->GetEventValue();
}

// --- cRecMenuNoRerunsFound  ---------------------------------------------------------
cRecMenuNoRerunsFound::cRecMenuNoRerunsFound(cString searchString) {
    SetWidthPercent(50);
    cString message = tr("No reruns found for Event");
    cString text = cString::sprintf("%s\n\"%s\"", 
                                    *message, 
                                    *searchString);
    cRecMenuItemInfo *infoItem = new cRecMenuItemInfo(*text);
    infoItem->CalculateHeight(width - 2 * border);
    AddMenuItem(infoItem);
    AddMenuItem(new cRecMenuItemButton(tr("OK"), rmsTimerConflictIgnoreReruns, true, true));
    CalculateHeight();
    CreatePixmap();
    Arrange();
}

// --- cRecMenuConfirmRerunUsed  ---------------------------------------------------------
cRecMenuConfirmRerunUsed::cRecMenuConfirmRerunUsed(const cEvent *original, const cEvent *replace) {
    SetWidthPercent(70);
#if VDRVERSNUM >= 20301
    LOCK_CHANNELS_READ;
    const cString channelOrig = Channels->GetByChannelID(original->ChannelID())->Name();
    const cString channelReplace = Channels->GetByChannelID(replace->ChannelID())->Name();
#else
    const cString channelOrig = Channels.GetByChannelID(original->ChannelID())->Name();
    const cString channelReplace = Channels.GetByChannelID(replace->ChannelID())->Name();
#endif
    cString message1 = tr("Timer for");
    cString message2 = tr("replaced by rerun");
    cString text = cString::sprintf("%s\n\"%s\", %s %s, %s\n%s\n\"%s\", %s %s, %s", 
                                    *message1, 
                                    original->Title(),
                                    *original->GetDateString(),
                                    *original->GetTimeString(),
                                    *channelOrig,
                                    *message2,
                                    replace->Title(),
                                    *replace->GetDateString(),
                                    *replace->GetTimeString(),
                                    *channelReplace);
    cRecMenuItemInfo *infoItem = new cRecMenuItemInfo(*text);
    infoItem->CalculateHeight(width - 2 * border);
    AddMenuItem(infoItem);
    AddMenuItem(new cRecMenuItemButton(tr("OK"), rmsTimerConflicts, true, true));
    CalculateHeight();
    CreatePixmap();
    Arrange();
}

// --- cRecMenuEditTimer  ---------------------------------------------------------
cRecMenuEditTimer::cRecMenuEditTimer(const cTimer *timer, eRecMenuState nextState) {
    SetWidthPercent(70);
    if (!timer)
        return;
    originalTimer = timer;
    cString title("");
    cString channelName("");
    if (timer->Event())
        title = timer->Event()->Title();
    if (timer->Channel())
        channelName = timer->Channel()->Name();
    cString infoText = cString::sprintf("%s:\n %s, %s", tr("Edit Timer"), *title, *channelName);
    cRecMenuItemInfo *infoItem = new cRecMenuItemInfo(*infoText, true);
    infoItem->CalculateHeight(width - 2 * border);
    AddMenuItemInitial(infoItem);
                
    timerActive = false;
    if (config.useRemoteTimers && pRemoteTimers) {
        RemoteTimers_GetMatch_v1_0 rtMatch;
        rtMatch.event = timer->Event();
        pRemoteTimers->Service("RemoteTimers::GetMatch-v1.0", &rtMatch);
        if (rtMatch.timer) {
            if (rtMatch.timerMatch == tmFull)
                timerActive = true;
        }
    } else
        timerActive = timer->HasFlags(tfActive);

    day = timer->Day();
    start = timer->Start();
    stop = timer->Stop();
    prio = timer->Priority();
    lifetime = timer->Lifetime();
    strncpy(folder, GetDirectoryFromTimer(timer->File()).c_str(), TEXTINPUTLENGTH);
    
    AddMenuItemInitial(new cRecMenuItemBool(tr("Timer Active"), true, &timerActive));
    AddMenuItemInitial(new cRecMenuItemInt(tr("Priority"), 0, MAXPRIORITY, false, &prio));
    AddMenuItemInitial(new cRecMenuItemInt(tr("Lifetime"), 0, MAXLIFETIME, false, &lifetime));
    AddMenuItemInitial(new cRecMenuItemDay(tr("Day"), false, &day));
    AddMenuItemInitial(new cRecMenuItemTime(tr("Timer start time"), false, &start));
    AddMenuItemInitial(new cRecMenuItemTime(tr("Timer stop time"), false, &stop));
    cString fileInfo = cString::sprintf("%s:\n%s", tr("Timer File"), timer->File());
    cRecMenuItemInfo *fileInfoItem = new cRecMenuItemInfo(*fileInfo, false);
    fileInfoItem->CalculateHeight(width - 2 * border);
    AddMenuItemInitial(fileInfoItem);
    AddMenuItemInitial(new cRecMenuItemSelectDirectory(tr("New Folder"), std::string(folder), false, folder));
    if (nextState == rmsTimelineTimerSave) {
        AddMenuItemInitial(new cRecMenuItemButton(tr("Delete Timer"), rmsTimelineTimerDelete, false, false));
        AddMenuItemInitial(new cRecMenuItemButtonYesNo(tr("Save"), tr("Cancel"), nextState, rmsTimeline, false));
    } else {
        AddMenuItemInitial(new cRecMenuItemButtonYesNo(tr("Save"), tr("Cancel"), nextState, rmsClose, false));
    }
    CalculateHeight();
    CreatePixmap();
    Arrange();
}

const cTimer *cRecMenuEditTimer::GetOriginalTimer(void) {
    return originalTimer;
}

cTimer *cRecMenuEditTimer::GetTimer(void) {
    cTimer *t = (cTimer *)originalTimer;
    if (timerActive)
        t->SetFlags(tfActive);
    else 
        t->ClrFlags(tfActive);
    t->SetDay(day);
    t->SetStart(start);
    t->SetStop(stop);
    t->SetPriority(prio);
    t->SetLifetime(lifetime);
    std::string newFolder(folder);
    std::string newFile = originalTimer->File();
    size_t found = newFile.find_last_of('~');
    if (found != std::string::npos) {
        std::string fileName = newFile.substr(found+1);
        if (newFolder.size() > 0)
            newFile = *cString::sprintf("%s~%s", newFolder.c_str(), fileName.c_str());
        else
            newFile = fileName;
    } else {
        if (newFolder.size() > 0)
            newFile = *cString::sprintf("%s~%s", newFolder.c_str(), newFile.c_str());
    }
    std::replace(newFile.begin(), newFile.end(), '/', '~');
    t->SetFile(newFile.c_str());
    return t;
}

/******************************************************************************************
*   Series Timer Menus
******************************************************************************************/

// --- cRecMenuSeriesTimer ---------------------------------------------------------
cRecMenuSeriesTimer::cRecMenuSeriesTimer(const cChannel *initialChannel, const cEvent *event, std::string folder) {
    if (!initialChannel)
        return;
    timerActive = true;
    channel = initialChannel->Number();
    dayOfWeek = 127; 
    priority =  MAXPRIORITY;
    lifetime = MAXLIFETIME;
    CalculateTimes(event);
    this->folder = folder;

    SetWidthPercent(70);
    cString title = tr("Create Series Timer based on");
    cString infoText = cString::sprintf("%s:\n%s", *title, event->Title());
    cRecMenuItemInfo *infoItem = new cRecMenuItemInfo(*infoText, true);
    infoItem->CalculateHeight(width - 2 * border);
    SetHeader(infoItem);

    AddMenuItem(new cRecMenuItemBool(tr("Timer Active"), false, &timerActive));
    AddMenuItem(new cRecMenuItemChannelChooser(tr("Channel"), false, &channel));
    AddMenuItem(new cRecMenuItemTime(tr("Series Timer start time"), false, &start));
    AddMenuItem(new cRecMenuItemTime(tr("Series Timer stop time"), false, &stop));
    AddMenuItem(new cRecMenuItemDayChooser(tr("Days to record"), false, &dayOfWeek));
    AddMenuItem(new cRecMenuItemDay(tr("Day to start"), false, &tstart));
    AddMenuItem(new cRecMenuItemInt(tr("Priority"), 0, MAXPRIORITY, false, &priority));
    AddMenuItem(new cRecMenuItemInt(tr("Lifetime"), 0, MAXLIFETIME, false, &lifetime));

    AddMenuItem(new cRecMenuItemButtonYesNo(tr("Create Timer"), tr("Cancel"), rmsSeriesTimerCreate, rmsClose, true));

    CalculateHeight();
    CreatePixmap();
    Arrange();
}

cTimer *cRecMenuSeriesTimer::GetTimer(void) {
#if VDRVERSNUM >= 20301
    LOCK_CHANNELS_READ;
    const cChannel *chan = Channels->GetByNumber(channel);
#else
    cChannel *chan = Channels.GetByNumber(channel);
#endif
    cTimer *seriesTimer = new cTimer(NULL, NULL, chan);
    cString fileName = "TITLE EPISODE";
    if (folder.size() > 0) {
        std::replace(folder.begin(), folder.end(), '/', '~');
        fileName = cString::sprintf("%s~%s", folder.c_str(), *fileName);
    }
    seriesTimer->SetDay(tstart);
    seriesTimer->SetStart(start);
    seriesTimer->SetStop(stop);
    seriesTimer->SetPriority(priority);
    seriesTimer->SetLifetime(lifetime);
    seriesTimer->SetWeekDays(dayOfWeek);
    seriesTimer->SetFile(*fileName);
    if (timerActive)
        seriesTimer->SetFlags(tfActive);
    else 
        seriesTimer->SetFlags(tfNone);
    return seriesTimer;
}

void cRecMenuSeriesTimer::CalculateTimes(const cEvent *event) {
    tstart = event->StartTime();
    tstart -= Setup.MarginStart * 60;
    time_t tstop = tstart + event->Duration();
    tstop  += Setup.MarginStop * 60;
    
    struct tm tm_r;
    struct tm *time = localtime_r(&tstart, &tm_r);
    start = time->tm_hour * 100 + time->tm_min;
    time = localtime_r(&tstop, &tm_r);
    stop = time->tm_hour * 100 + time->tm_min;
    if (stop >= 2400)
        stop -= 2400;
}

// --- cRecMenuConfirmSeriesTimer  ---------------------------------------------------------
cRecMenuConfirmSeriesTimer::cRecMenuConfirmSeriesTimer(cTimer *seriesTimer) {
    SetWidthPercent(50);
    cString message = tr("Series Timer created");
    cString infoText = message;
    if (seriesTimer) {
        cString days = cTimer::PrintDay(seriesTimer->Day(), seriesTimer->WeekDays(), true);
        infoText = cString::sprintf("%s\n%s, %s: %s, %s: %s", *message, *days, tr("Start"), *TimeString(seriesTimer->StartTime()), tr("Stop"), *TimeString(seriesTimer->StopTime()));
    }
    cRecMenuItemInfo *infoItem = new cRecMenuItemInfo(*infoText);
    infoItem->CalculateHeight(width - 2 * border);
    AddMenuItem(infoItem);
    AddMenuItem(new cRecMenuItemButton(tr("OK"), rmsClose, true, true));
    CalculateHeight();
    CreatePixmap();
    Arrange();
}

/******************************************************************************************
*   SearchTimer Menus
******************************************************************************************/

// --- cRecMenuSearchTimer  ---------------------------------------------------------
cRecMenuSearchTimer::cRecMenuSearchTimer(const cEvent *event) {
    SetWidthPercent(70);
    cString message = tr("Configure Search Timer based on");
    cString infoText = cString::sprintf("%s:\n\"%s\"", *message, event->Title());
    cRecMenuItemInfo *infoItem = new cRecMenuItemInfo(*infoText, true);
    infoItem->CalculateHeight(width - 2 * border);
    SetHeader(infoItem);
    strncpy(searchString, event->Title(), TEXTINPUTLENGTH);
    AddMenuItemInitial(new cRecMenuItemText(tr("Search Expression:"), TEXTINPUTLENGTH, false, searchString));
    AddMenuItemInitial(new cRecMenuItemButtonYesNo(tr("Continue"), tr("Cancel"), rmsSearchTimerOptions, rmsClose, true));
    CalculateHeight();
    CreatePixmap();
    Arrange();
}

// --- cRecMenuSearchTimerTemplates  ---------------------------------------------------------
cRecMenuSearchTimerTemplates::cRecMenuSearchTimerTemplates(cTVGuideSearchTimer searchTimer, std::vector<TVGuideEPGSearchTemplate> templates) {
    this->searchTimer = searchTimer;
    this->templates = templates;
    SetWidthPercent(70);
    cString message = tr("Configure Search Timer for Search String");
    cString infoText = cString::sprintf("%s:\n%s", *message, searchTimer.GetSearchString().c_str());
    cRecMenuItemInfo *infoItem = new cRecMenuItemInfo(*infoText, true);
    infoItem->CalculateHeight(width - 2 * border);
    SetHeader(infoItem);
    
    AddMenuItemInitial(new cRecMenuItemButton(tr("Manually configure Options"), rmsSearchTimerEdit, true));
    
    numTemplates = templates.size();
    for (int i=0; i<numTemplates; i++) {
        cString buttonText = cString::sprintf("%s \"%s\"", tr("Use Template"), templates[i].name.c_str());
        if (!AddMenuItemInitial(new cRecMenuItemButton(*buttonText, rmsSearchTimerCreateWithTemplate, false)))
            break;
    }
    CalculateHeight();
    CreatePixmap();
    Arrange();
}
    
cRecMenuItem *cRecMenuSearchTimerTemplates::GetMenuItem(int number) {
    if (number == 0) {
        return new cRecMenuItemButton(tr("Manually configure Options"), rmsSearchTimerEdit, false);
    } else if ((number > 0) && (number < numTemplates + 1)) {
        cString buttonText = cString::sprintf("%s \"%s\"", tr("Use Template"), templates[number-1].name.c_str());
        cRecMenuItem *templ = new cRecMenuItemButton(*buttonText, rmsSearchTimerCreateWithTemplate, false);
        return templ;
    }
    return NULL;
}

int cRecMenuSearchTimerTemplates::GetTotalNumMenuItems(void) { 
    return numTemplates + 1;
}

TVGuideEPGSearchTemplate cRecMenuSearchTimerTemplates::GetTemplate(void) {
    TVGuideEPGSearchTemplate templ;
    int tmplActive = GetActive() - 1;
    if (tmplActive >= 0 && tmplActive < (int)templates.size())
        templ = templates[tmplActive];
    return templ;
}
// --- cRecMenuSearchTimers  ---------------------------------------------------------
cRecMenuSearchTimers::cRecMenuSearchTimers(std::vector<cTVGuideSearchTimer> searchTimers) {
    this->searchTimers = searchTimers;
    numSearchTimers = searchTimers.size();
    SetWidthPercent(70);
    cString headline;
    if (numSearchTimers > 0) {
        headline = tr("EPGSearch Search Timers");
    } else {
        headline = tr("No Search Timers Configured");
    } 
    cRecMenuItemInfo *infoItem = new cRecMenuItemInfo(*headline, true);
    infoItem->CalculateHeight(width - 2 * border);
    SetHeader(infoItem);
    cRecMenuItem *button = new cRecMenuItemButton(tr("Close"), rmsClose, (!numSearchTimers)?true:false);
    SetFooter(button);
    if (numSearchTimers > 0)
        SetMenuItems();    
    CalculateHeight();
    CreatePixmap();
    Arrange();
}

cRecMenuSearchTimers::~cRecMenuSearchTimers(void) {

}

void cRecMenuSearchTimers::SetMenuItems(void) {
    for (int i = 0; i < numSearchTimers; i++) {
        if (!AddMenuItemInitial(new cRecMenuItemSearchTimer(searchTimers[i], rmsSearchTimerTest, rmsSearchTimerEdit, rmsSearchTimerDeleteConfirm, (i==0)?true:false)))
            break;
    }
}

cTVGuideSearchTimer cRecMenuSearchTimers::GetSearchTimer(void) {
    cRecMenuItemSearchTimer *activeItem = dynamic_cast<cRecMenuItemSearchTimer*>(GetActiveMenuItem());
    return activeItem->GetTimer();
}

cRecMenuItem *cRecMenuSearchTimers::GetMenuItem(int number) {
    if (number < 0 || number >= numSearchTimers)
        return NULL;
    return new cRecMenuItemSearchTimer(searchTimers[number], rmsSearchTimerTest, rmsSearchTimerEdit, rmsSearchTimerDeleteConfirm, false);
}

int cRecMenuSearchTimers::GetTotalNumMenuItems(void) {
    return numSearchTimers;
}

// --- cRecMenuSearchTimerEdit  ---------------------------------------------------------
cRecMenuSearchTimerEdit::cRecMenuSearchTimerEdit(cTVGuideSearchTimer searchTimer, std::vector<std::string> channelGroups) {
    init = true;
    deleteMenuItems = false;
    this->sT = searchTimer;
    this->channelGroups = channelGroups;
    strncpy(searchString, sT.searchString.c_str(), TEXTINPUTLENGTH);
    channelgroupIndex = -1;
    std::string dir = sT.directory;
    strncpy(directory, dir.c_str(), TEXTINPUTLENGTH);
    dayOfWeek = DayOfWeek(sT.dayOfWeek);
//    dsyslog("Weekday = %i, %i",  sT.dayOfWeek, dayOfWeek);
    indent = "   ";

    if (sT.useChannel == 1) {
        startChannel = (sT.channelMin) ? sT.channelMin->Number() : 0;
        stopChannel = (sT.channelMax) ? sT.channelMax->Number() : 0;
        if (startChannel == 0) startChannel = 1;
        if (stopChannel == 0) stopChannel = 1;
    }

    sT.GetSearchModes(&searchModes);
    sT.GetUseChannelModes(&useChannelModes);
    sT.GetCompareDateModes(&compareDateModes);
    sT.GetSearchTimerModes(&searchTimerModes);
    sT.GetDelModes(&delModes);
    channelgroupIndex = SplitChannelGroups(&channelGroups, &channelgroups);

    SetWidthPercent(70);
    cString infoText;
    if (sT.GetID() > -1) {
        infoText = tr("Configure Search Timer Options");
    } else {
        infoText = tr("Create Search Timer");
    }
    cRecMenuItemInfo *infoItem = new cRecMenuItemInfo(*infoText, true);
    infoItem->CalculateHeight(width - 2 * border);
    SetHeader(infoItem);
    cRecMenuItemButtonYesNo *footerButton = new cRecMenuItemButtonYesNo(tr("Save Search Timer"), tr("Cancel"), rmsSearchTimerSave, rmsSearchTimers, false);
    SetFooter(footerButton);
    CreateMenuItems();
}

cRecMenuSearchTimerEdit::~cRecMenuSearchTimerEdit(void) {
    for (std::vector<cRecMenuItem*>::iterator it = mainMenuItems.begin(); it != mainMenuItems.end(); it++) {
        delete *it;
    }
    mainMenuItems.clear();
}

int cRecMenuSearchTimerEdit::DayOfWeek(int dayofWeek) {
    int vdrDayOfWeek = 0;
    if (dayofWeek > 0) {
        vdrDayOfWeek = pow(2, (dayofWeek + 6) % 7);
    } else if (dayofWeek < 0) {
        int absDayOfWeek = abs(dayofWeek);
        for (int i = 0; i < 7; i++) {
            if (absDayOfWeek & (1 << i)) {
                vdrDayOfWeek += pow(2, (i + 6) % 7);
            }
        }
    }
    return vdrDayOfWeek;
}

int cRecMenuSearchTimerEdit::SetDayOfWeek(int VDRDayOfWeek) {
    int epgSearchDayOfWeek = 0;
    for (int i=0; i < 7; i++) {
        if (VDRDayOfWeek & (1 << i)) {
            epgSearchDayOfWeek += pow(2, (i+1)%7);
        }
    }
    return epgSearchDayOfWeek * (-1);
}

int cRecMenuSearchTimerEdit::SplitChannelGroups(std::vector<std::string> *channelGroups, std::vector<std::string> *channelgroups) {
    int i = 0;
    int j = 0;
    for (std::vector<std::string>::iterator it = channelGroups->begin(); it != channelGroups->end(); it++) {
        std::string a = *it;
        splitstring s(a.c_str());
        std::vector<std::string> value = s.split('|', 0);
        std::vector<std::string>::iterator ito = value.begin();
        channelgroups->push_back(*ito);
        std::string b = *ito;
        if (b.compare(sT.channelGroup) == 0)
            j = i;
        i++;
    }
    return j;
}

void cRecMenuSearchTimerEdit::CreateMenuItems(void) {

    int activeMenuItem = 0;

    if (mainMenuItems.size() > 0) {
        for (long unsigned int index = 0; index < mainMenuItems.size(); index++) {
            if (mainMenuItems[index]->isActive()) {
                activeMenuItem = index;
                break;
            }
        }
        mainMenuItems.clear();
    }

    mainMenuItems.push_back(new cRecMenuItemText(tr("Search term"), TEXTINPUTLENGTH, init, searchString));
    mainMenuItems.push_back(new cRecMenuItemBool(tr("Active"), false, &sT.useAsSearchTimer, rmsSearchTimerSave, true));
    mainMenuItems.push_back(new cRecMenuItemSelect(tr("Search mode"), searchModes, false, &sT.mode, rmsSearchTimerSave, true));
    if (sT.mode == 5) {
        mainMenuItems.push_back(new cRecMenuItemInt(cString::sprintf("%s%s", *indent, tr("Tolerance")), 1, 9, false, &sT.fuzzyTolerance, rmsSearchTimerSave));
    }
    mainMenuItems.push_back(new cRecMenuItemBool(tr("Match case"), false, &sT.useCase, rmsSearchTimerSave));
    mainMenuItems.push_back(new cRecMenuItemBool(tr("Use title"), false, &sT.useTitle, rmsSearchTimerSave));
    mainMenuItems.push_back(new cRecMenuItemBool(tr("Use subtitle"), false, &sT.useSubtitle, rmsSearchTimerSave));
    mainMenuItems.push_back(new cRecMenuItemBool(tr("Use description"), false, &sT.useDescription, rmsSearchTimerSave));
//    mainMenuItems.push_back(new cRecMenuItemBool(tr("Use content descriptor"), false, &sT.useContentDescriptors, rmsSearchTimerSave));
    mainMenuItems.push_back(new cRecMenuItemSelect(tr("Use channel"), useChannelModes, false, &sT.useChannel, rmsSearchTimerSave, true));
    if (sT.useChannel == 1) {
        mainMenuItems.push_back(new cRecMenuItemChannelChooser(cString::sprintf("%s%s", *indent, tr("from channel")), false, &startChannel, rmsSearchTimerSave));
        mainMenuItems.push_back(new cRecMenuItemChannelChooser(cString::sprintf("%s%s", *indent, tr("to channel")), false, &stopChannel, rmsSearchTimerSave));
    }
    else if ((sT.useChannel == 2) && (channelgroups.size() > 0)) {
        mainMenuItems.push_back(new cRecMenuItemSelect(cString::sprintf("%s%s", *indent, tr("Channel group")), channelgroups, false, &channelgroupIndex, rmsSearchTimerSave, false));
    }
    mainMenuItems.push_back(new cRecMenuItemBool(tr("Use time"), false, &sT.useTime, rmsSearchTimerSave, true));
    if (sT.useTime) {
        mainMenuItems.push_back(new cRecMenuItemTime(cString::sprintf("%s%s", *indent, tr("Start after")), false, &sT.startTime, rmsSearchTimerSave));
        mainMenuItems.push_back(new cRecMenuItemTime(cString::sprintf("%s%s", *indent, tr("Start before")), false, &sT.stopTime, rmsSearchTimerSave));
    }
    mainMenuItems.push_back(new cRecMenuItemBool(tr("Use duration"), false, &sT.useDuration, rmsSearchTimerSave, true));
    if (sT.useDuration) {
        mainMenuItems.push_back(new cRecMenuItemTime(cString::sprintf("%s%s", *indent, tr("Min. duration")), false, &sT.minDuration, rmsSearchTimerSave));
        mainMenuItems.push_back(new cRecMenuItemTime(cString::sprintf("%s%s", *indent, tr("Max. duration")), false, &sT.maxDuration, rmsSearchTimerSave));
    }
    mainMenuItems.push_back(new cRecMenuItemBool(tr("Use day of week"), false, &sT.useDayOfWeek, rmsSearchTimerSave, true));
    if (sT.useDayOfWeek)
        mainMenuItems.push_back(new cRecMenuItemDayChooser(cString::sprintf("%s%s", *indent, tr("Day of week")), false, &dayOfWeek));
    mainMenuItems.push_back(new cRecMenuItemBool(tr("Use in Favorites"), false, &sT.useInFavorites, rmsSearchTimerSave));
    mainMenuItems.push_back(new cRecMenuItemBool(tr("Use as search timer"), false, &sT.useAsSearchTimer, rmsSearchTimerSave, true));
    if (sT.useAsSearchTimer) {
        mainMenuItems.push_back(new cRecMenuItemSelect(cString::sprintf("%s%s", *indent, tr("Action")), searchTimerModes, false, &sT.action, rmsSearchTimerSave, true));
        if (sT.action == searchTimerActionSwitchOnly) {
            mainMenuItems.push_back(new cRecMenuItemInt(cString::sprintf("%s%s%s", *indent, *indent, tr("Switch ... minutes before start")), 0, 99, false, &sT.switchMinsBefore, rmsSearchTimerSave));
            mainMenuItems.push_back(new cRecMenuItemBool(cString::sprintf("%s%s%s", *indent, *indent, tr("Unmute sound")), false, &sT.unmuteSoundOnSwitch, rmsSearchTimerSave));
        }
        if (sT.action ==  searchTimerActionAnnounceAndSwitch) {
            mainMenuItems.push_back(new cRecMenuItemInt(cString::sprintf("%s%s%s", *indent, *indent, tr("Ask ... minutes before start")), 0, 99, false, &sT.switchMinsBefore, rmsSearchTimerSave));
            mainMenuItems.push_back(new cRecMenuItemBool(cString::sprintf("%s%s%s", *indent, *indent, tr("Unmute sound")), false, &sT.unmuteSoundOnSwitch, rmsSearchTimerSave));
        }
        if ((sT.action == searchTimerActionRecord) || (sT.action == searchTimerActionInactiveRecord)) {
            mainMenuItems.push_back(new cRecMenuItemBool(cString::sprintf("%s%s%s", *indent, *indent, tr("Series Recording")), false, &sT.useEpisode, rmsSearchTimerSave));
            mainMenuItems.push_back(new cRecMenuItemSelectDirectory(cString::sprintf("%s%s%s", *indent, *indent, tr("Directory")), std::string(directory), false, directory, rmsSearchTimerSave, true));
            mainMenuItems.push_back(new cRecMenuItemInt(cString::sprintf("%s%s%s", *indent, *indent, tr("Delete recordings after ... days")), 0, 999, false, &sT.delAfterDays, rmsSearchTimerSave));
            if (sT.delAfterDays > 0) {
                mainMenuItems.push_back(new cRecMenuItemInt(cString::sprintf("%s%s%s%s", *indent, *indent, *indent, tr("Keep ... recordings")), 0, 999, false, &sT.recordingsKeep, rmsSearchTimerSave));
            }
            mainMenuItems.push_back(new cRecMenuItemInt(cString::sprintf("%s%s%s", *indent, *indent, tr("Pause when ... recordings exist")), 0, 999, false, &sT.pauseOnNrRecordings, rmsSearchTimerSave));
            mainMenuItems.push_back(new cRecMenuItemBool(cString::sprintf("%s%s%s", *indent, *indent, tr("Avoid Repeats")), false, &sT.avoidRepeats, rmsSearchTimerSave, true));
            if (sT.avoidRepeats) {
                mainMenuItems.push_back(new cRecMenuItemInt(cString::sprintf("%s%s%s%s", *indent, *indent, *indent, tr("Allowed repeats")), 0, 99, false, &sT.allowedRepeats, rmsSearchTimerSave));
                if (sT.allowedRepeats > 0) {
                    mainMenuItems.push_back(new cRecMenuItemInt(cString::sprintf("%s%s%s%s%s", *indent, *indent, *indent, *indent, tr("Only repeats within ... days")), 0, 999, false, &sT.repeatsWithinDays, rmsSearchTimerSave));
                }
                mainMenuItems.push_back(new cRecMenuItemBool(cString::sprintf("%s%s%s%s", *indent, *indent, *indent, tr("Compare Title")), false, &sT.compareTitle, rmsSearchTimerSave));
                mainMenuItems.push_back(new cRecMenuItemBool(cString::sprintf("%s%s%s%s", *indent, *indent, *indent, tr("Compare Subtitle")), false, &sT.compareSubtitle, rmsSearchTimerSave));
                mainMenuItems.push_back(new cRecMenuItemBool(cString::sprintf("%s%s%s%s", *indent, *indent, *indent, tr("Compare Description")), false, &sT.compareSummary, rmsSearchTimerSave, true));
                if (sT.compareSummary) {
                    mainMenuItems.push_back(new cRecMenuItemInt(cString::sprintf("%s%s%s%s%s", *indent, *indent, *indent, *indent, tr("Min. match in %")), 1, 100, false, &sT.compareSummaryMatchInPercent, rmsSearchTimerSave));
                }
                mainMenuItems.push_back(new cRecMenuItemSelect(cString::sprintf("%s%s%s%s", *indent, *indent, *indent, tr("Compare date")), compareDateModes, false, &sT.compareDate, rmsSearchTimerSave, false));
            }
            mainMenuItems.push_back(new cRecMenuItemInt(cString::sprintf("%s%s%s", *indent, *indent, tr("Priority")), 0, 99, false, &sT.priority, rmsSearchTimerSave));
            mainMenuItems.push_back(new cRecMenuItemInt(cString::sprintf("%s%s%s", *indent, *indent, tr("Lifetime")), 0, 99, false, &sT.lifetime, rmsSearchTimerSave));
            mainMenuItems.push_back(new cRecMenuItemInt(cString::sprintf("%s%s%s", *indent, *indent, tr("Time margin for start in minutes")), 0, 30, false, &sT.marginStart, rmsSearchTimerSave));
            mainMenuItems.push_back(new cRecMenuItemInt(cString::sprintf("%s%s%s", *indent, *indent, tr("Time margin for stop in minutes")), 0, 30, false, &sT.marginStop, rmsSearchTimerSave));
            mainMenuItems.push_back(new cRecMenuItemBool(cString::sprintf("%s%s%s", *indent, *indent, tr("Use VPS")), false, &sT.useVPS, rmsSearchTimerSave));
            mainMenuItems.push_back(new cRecMenuItemSelect(cString::sprintf("%s%s%s", *indent, *indent, tr("Auto delete")), delModes, false, &sT.delMode, rmsSearchTimerSave, true));
            if (sT.delMode == 1)
                mainMenuItems.push_back(new cRecMenuItemInt(cString::sprintf("%s%s%s%s", *indent, *indent, *indent, tr("after ... recordings")), 0, 999, false, &sT.delAfterCountRecs, rmsSearchTimerSave));
            else if (sT.delMode == 2)
                mainMenuItems.push_back(new cRecMenuItemInt(cString::sprintf("%s%s%s%s", *indent, *indent, *indent, tr("after ... days after first rec.")), 0, 999, false, &sT.delAfterDaysOfFirstRec, rmsSearchTimerSave));
        }
    }
    mainMenuItems.push_back(new cRecMenuItemButton(tr("Display Results for Search Timer"), rmsSearchTimerTest, false));

    bool reDraw = false;
    if (GetCurrentNumMenuItems() > 0) {
        InitMenu(false);
        reDraw = true;
    }
    
    numMenuItems = mainMenuItems.size();

    int start = GetStartIndex();
    for (int i = start; i < numMenuItems; i++) {
        if (!AddMenuItemInitial(mainMenuItems[i])) {
            break;
        }
    }
    if (reDraw)
        mainMenuItems[activeMenuItem]->setActive();

    if (init) {
        init = !init;
    }
    CalculateHeight(!reDraw);
    CreatePixmap();
    Arrange();
}

cTVGuideSearchTimer cRecMenuSearchTimerEdit::GetSearchTimer(void) {
    sT.searchString = searchString;
    if (sT.useChannel == 1) {
#if VDRVERSNUM >= 20301
        {
        LOCK_CHANNELS_READ;
        sT.channelMin = Channels->GetByNumber(startChannel);
        sT.channelMax = Channels->GetByNumber(stopChannel);
        }
#else
        sT.channelMin = Channels.GetByNumber(startChannel);
        sT.channelMax = Channels.GetByNumber(stopChannel);
#endif
    }
    if (sT.useChannel == 2) {
        if (channelgroups.size() > 0) {
            std::string & channelGroup = channelgroups[channelgroupIndex];
            sT.channelGroup = channelGroup;
        } else {
            sT.useChannel = 0;
        }
    }
    if (sT.useDayOfWeek) {
        sT.dayOfWeek = SetDayOfWeek(dayOfWeek);
    }
    std::string dir(directory);
    std::replace(dir.begin(), dir.end(), '/', '~');
    sT.directory = dir;
    return sT;
}

int cRecMenuSearchTimerEdit::GetTotalNumMenuItems(void) { 
    return numMenuItems; 
}

cRecMenuItem *cRecMenuSearchTimerEdit::GetMenuItem(int number) {
    if ((number > -1) && (number < numMenuItems)) {
        return mainMenuItems[number];
    }
    return NULL;
}

// --- cRecMenuSearchTimerDeleteConfirm ---------------------------------------------
cRecMenuSearchTimerDeleteConfirm::cRecMenuSearchTimerDeleteConfirm(cTVGuideSearchTimer searchTimer) {
    this->searchTimer = searchTimer;
    SetWidthPercent(70);
    cString message = tr("Really delete Search Timer");
    cString infoText = cString::sprintf("%s \"%s\"?", *message, searchTimer.GetSearchString().c_str());
    cRecMenuItemInfo *infoItem = new cRecMenuItemInfo(*infoText, true);
    infoItem->CalculateHeight(width - 2 * border);
    SetHeader(infoItem);
    AddMenuItem(new cRecMenuItemButton(tr("Delete only Search Timer"), rmsSearchTimerDelete, true));
    AddMenuItem(new cRecMenuItemButton(tr("Delete Search Timer and created Timers"), rmsSearchTimerDeleteWithTimers, false));
    SetFooter(new cRecMenuItemButton(tr("Cancel"), rmsClose, false));
    CalculateHeight();
    CreatePixmap();
    Arrange();
}

cRecMenuSearchTimerDeleteConfirm::~cRecMenuSearchTimerDeleteConfirm(void) {

}

cTVGuideSearchTimer cRecMenuSearchTimerDeleteConfirm::GetSearchTimer(void) {
    return searchTimer;
}

// --- cRecMenuSearchTimerCreateConfirm  ---------------------------------------------------------
cRecMenuSearchTimerCreateConfirm::cRecMenuSearchTimerCreateConfirm(bool success) {
    SetWidthPercent(50);
    
    cString message1a = tr("Search Timer sucessfully created.");
    cString message1b = tr ("Search Timer update initialised");
    cString message1 = cString::sprintf("%s\n%s", *message1a, *message1b);
    cString message2 = tr("Search Timer NOT sucessfully created");
    cString infoText = success?message1:message2;
    cRecMenuItemInfo *infoItem = new cRecMenuItemInfo(*infoText);
    infoItem->CalculateHeight(width - 2 * border);
    AddMenuItem(infoItem);

    AddMenuItem(new cRecMenuItemButton(tr("OK"), rmsClose, true));
    
    CalculateHeight();
    CreatePixmap();
    Arrange();
}

// --- cRecMenuSearchTimerTemplatesCreate  ---------------------------------------------------------
cRecMenuSearchTimerTemplatesCreate::cRecMenuSearchTimerTemplatesCreate(TVGuideEPGSearchTemplate templ, cTVGuideSearchTimer searchTimer) {
    this->templ = templ;
    this->searchTimer = searchTimer;
    SetWidthPercent(70);

    cString message1 = tr("Creating Search Timer");
    cString message2 = tr("Search Term");
    cString message3 = tr("Using Template");
    
    cString infoText = cString::sprintf("%s\n%s: \"%s\"\n%s \"%s\"", *message1, *message2, searchTimer.GetSearchString().c_str(), *message3, templ.name.c_str());
    cRecMenuItemInfo *infoItem = new cRecMenuItemInfo(*infoText);
    infoItem->CalculateHeight(width - 2 * border);
    AddMenuItem(infoItem);

    AddMenuItem(new cRecMenuItemButton(tr("Display Results for Search Timer"), rmsSearchTimerTest, true));
    AddMenuItem(new cRecMenuItemButtonYesNo(tr("Create Search Timer"), tr("Use other Template"), rmsSearchTimerSave, rmsSearchTimerOptions, false));
    
    CalculateHeight();
    CreatePixmap();
    Arrange();
}


// --- cRecMenuSearchTimerResults ---------------------------------------------------------
cRecMenuSearchTimerResults::cRecMenuSearchTimerResults(std::string searchString, const cEvent **searchResults, int numResults, std::string templateName, eRecMenuState action2) {
    this->searchResults = searchResults;
    this->action2 = action2;
    this->numResults = numResults;
    SetWidthPercent(70);
    cString message1 = "", message2 = "", message3 = "", infoText = "";
    if (action2 == rmsFavoritesRecord) {
        message1 = tr("search results for Favorite");
        message2 = tr("search result for Favorite");
    } else {
        message1 = tr("search results for Search Timer");
        message2 = tr("search result for Search Timer");
        message3 = tr("Using Template");
    }
    if (templateName.size() > 0) {
        infoText = cString::sprintf("%d %s:\n\"%s\"\n%s \"%s\"", numResults, (numResults>1)?(*message1):(*message2), searchString.c_str(), *message3, templateName.c_str());
    } else {
        infoText = cString::sprintf("%d %s:\n\"%s\"", numResults, (numResults>1)?(*message1):(*message2), searchString.c_str());
    }
    cRecMenuItem *infoItem = new cRecMenuItemInfo(*infoText, true);
    infoItem->CalculateHeight(width - 2 * border);
    SetHeader(infoItem);
    
    cRecMenuItem *buttons = new cRecMenuItemButton(tr("Close"), rmsClose, false);
    SetFooter(buttons);
    if (searchResults && (numResults > 0)) {
        for (int i=0; i<numResults; i++) {
            if (!AddMenuItemInitial(new cRecMenuItemEvent(searchResults[i], rmsSearchShowInfo, action2, (i==0)?true:false)))
                break;
        }
    }
    CalculateHeight();
    CreatePixmap();
    Arrange();
}
    
cRecMenuItem *cRecMenuSearchTimerResults::GetMenuItem(int number) { 
    if ((number >= 0) && (number < numResults)) {
        cRecMenuItem *result = new cRecMenuItemEvent(searchResults[number], rmsSearchShowInfo, action2, false);
        return result;
    }
    return NULL;
}

int cRecMenuSearchTimerResults::GetTotalNumMenuItems(void) { 
    return numResults;
}

const cEvent *cRecMenuSearchTimerResults::GetEvent(void) {
    const cEvent *ev = NULL;
    if (cRecMenuItemEvent *activeItem = dynamic_cast<cRecMenuItemEvent*>(GetActiveMenuItem()))
        ev = activeItem->GetEventValue();
    return ev;
}

// --- cRecMenuSearchTimerNothingFound  ---------------------------------------------------------
cRecMenuSearchTimerNothingFound::cRecMenuSearchTimerNothingFound(std::string searchString) {
    SetWidthPercent(50);
    cString message = tr("Nothing found for Search String");
    cString text;
    text = cString::sprintf("%s\n\"%s\"", 
                            *message, 
                            searchString.c_str());
    cRecMenuItemInfo *infoItem = new cRecMenuItemInfo(*text);
    infoItem->CalculateHeight(width - 2 * border);
    AddMenuItem(infoItem);
    AddMenuItem(new cRecMenuItemButton(tr("OK"), rmsClose, true, true));
    CalculateHeight();
    CreatePixmap();
    Arrange();
}

/******************************************************************************************
*   SwitchTimer Menus
******************************************************************************************/

// --- cRecMenuSwitchTimer  ---------------------------------------------------------
cRecMenuSwitchTimer::cRecMenuSwitchTimer(void) {
    switchMinsBefore = config.switchMinsBefore;
    switchMode = config.switchMode;

    SetWidthPercent(60);
    
    cString infoText = tr("Configure Options for Switchtimer");
    cRecMenuItemInfo *infoItem = new cRecMenuItemInfo(*infoText, true);
    infoItem->CalculateHeight(width - 2 * border);
    AddMenuItem(infoItem);

    AddMenuItem(new cRecMenuItemInt(tr("Minutes before switching"), 0, 10, false, &switchMinsBefore));
    std::vector<std::string> switchModeItems;
    switchModeItems.push_back(tr("switch"));
    switchModeItems.push_back(tr("announce only"));
    switchModeItems.push_back(tr("ask for switch"));
    AddMenuItem(new cRecMenuItemSelect(tr("Switch Mode"), switchModeItems, false, &switchMode));
    
    AddMenuItem(new cRecMenuItemButtonYesNo(tr("Create"), tr("Cancel"), rmsSwitchTimerCreate, rmsClose, true));
    
    CalculateHeight();
    CreatePixmap();
    Arrange();
}

cSwitchTimer cRecMenuSwitchTimer::GetSwitchTimer(void) {
    cSwitchTimer st;
    st.switchMinsBefore = switchMinsBefore;
    st.switchMode = switchMode;
    return st;
}

// --- cRecMenuSwitchTimerConfirm  ---------------------------------------------------------
cRecMenuSwitchTimerConfirm::cRecMenuSwitchTimerConfirm(bool success) {
    SetWidthPercent(50);
    
    cString message1 = tr("Switch Timer sucessfully created");
    cString message2 = tr("Switch Timer NOT sucessfully created");
    cString infoText = success?message1:message2;
    cRecMenuItemInfo *infoItem = new cRecMenuItemInfo(*infoText);
    infoItem->CalculateHeight(width - 2 * border);
    AddMenuItem(infoItem);

    AddMenuItem(new cRecMenuItemButton(tr("OK"), rmsClose, true));
    
    CalculateHeight();
    CreatePixmap();
    Arrange();
}

// --- cRecMenuSwitchTimerDelete  ---------------------------------------------------------
cRecMenuSwitchTimerDelete::cRecMenuSwitchTimerDelete(void) {
    SetWidthPercent(50);
    
    cString infoText = tr("Switch Timer deleted");
    cRecMenuItemInfo *infoItem = new cRecMenuItemInfo(*infoText);
    infoItem->CalculateHeight(width - 2 * border);
    AddMenuItem(infoItem);

    AddMenuItem(new cRecMenuItemButton(tr("OK"), rmsClose, true));
    
    CalculateHeight();
    CreatePixmap();
    Arrange();
}

/******************************************************************************************
*   Search Menus
******************************************************************************************/


// --- cRecMenuSearch  ---------------------------------------------------------
cRecMenuSearch::cRecMenuSearch(std::string searchString, bool withOptions) {
    strncpy(this->searchString, searchString.c_str(), TEXTINPUTLENGTH);
    mode = 0;
    channelNr = 0;
    useTitle = true;
    useSubTitle = true;
    useDescription = false;
    SetWidthPercent(60);
    cString infoText = tr("Search");
    cRecMenuItemInfo *infoItem = new cRecMenuItemInfo(*infoText, true);
    infoItem->CalculateHeight(width - 2 * border);
    SetHeader(infoItem);
    AddMenuItem(new cRecMenuItemText(tr("Search Expression:"), TEXTINPUTLENGTH, false, this->searchString));
    if (withOptions) {
        std::vector<std::string> searchModes;
        cTVGuideSearchTimer searchTimer;
        searchTimer.GetSearchModes(&searchModes);
        AddMenuItemInitial(new cRecMenuItemSelect(tr("Search Mode"), searchModes, false, &mode));
        AddMenuItemInitial(new cRecMenuItemChannelChooser(tr("Channel to Search"), false, &channelNr));
        AddMenuItemInitial(new cRecMenuItemBool(tr("Search in title"), false, &useTitle));
        AddMenuItemInitial(new cRecMenuItemBool(tr("Search in Subtitle"), false, &useSubTitle));
        AddMenuItemInitial(new cRecMenuItemBool(tr("Search in Description"), false, &useDescription));
    } else {
        AddMenuItemInitial(new cRecMenuItemButton(tr("Show Search Options"), rmsSearchWithOptions, false));
    }
    cRecMenuItemButtonYesNo *button = new cRecMenuItemButtonYesNo(tr("Perform Search"), tr("Cancel"), rmsSearchPerform, rmsClose, true);
    SetFooter(button);
    CalculateHeight();
    CreatePixmap();
    Arrange();
}

Epgsearch_searchresults_v1_0 cRecMenuSearch::GetEPGSearchStruct(void) {
    Epgsearch_searchresults_v1_0 data;
    data.query = searchString;
    data.mode = mode;
    data.channelNr = channelNr;
    data.useTitle = useTitle;
    data.useSubTitle = useSubTitle;
    data.useDescription = useDescription;
    return data;
}


// --- cRecMenuSearchResults  ---------------------------------------------------------
cRecMenuSearchResults::cRecMenuSearchResults(std::string searchString, const cEvent **searchResults, int numResults) {
    this->searchResults = searchResults;
    SetWidthPercent(70);
    this->searchString = searchString;
    this->numResults = numResults;
    cString message1 = tr("search results for");
    cString message2 = tr("search result for");
    cString infoText = cString::sprintf("%d %s:\n\"%s\"", numResults, (numResults>1)?(*message1):(*message2), searchString.c_str());
    cRecMenuItem *infoItem = new cRecMenuItemInfo(*infoText, true);
    infoItem->CalculateHeight(width - 2 * border);
    SetHeader(infoItem);
    
    cRecMenuItem *buttons = new cRecMenuItemButtonYesNo(tr("Adapt Search"), tr("Close"), rmsSearch, rmsClose, false);
    SetFooter(buttons);
    if (searchResults && (numResults > 0)) {
        for (int i=0; i<numResults; i++) {
            if (!AddMenuItemInitial(new cRecMenuItemEvent(searchResults[i], rmsSearchShowInfo, rmsSearchRecord, (i==0)?true:false)))
                break;
        }
    }
    CalculateHeight();
    CreatePixmap();
    Arrange();
}

cRecMenuItem *cRecMenuSearchResults::GetMenuItem(int number) { 
    if ((number >= 0) && (number < numResults)) {
        cRecMenuItem *result = new cRecMenuItemEvent(searchResults[number], rmsSearchShowInfo, rmsSearchRecord, false);
        return result;
    }
    return NULL;
}

int cRecMenuSearchResults::GetTotalNumMenuItems(void) { 
    return numResults;
}

const cEvent *cRecMenuSearchResults::GetEvent(void) {
    const cEvent *ev = NULL;
    if (cRecMenuItemEvent *activeItem = dynamic_cast<cRecMenuItemEvent*>(GetActiveMenuItem()))
        ev = activeItem->GetEventValue();
    return ev;
}


// --- cRecMenuSearchConfirmTimer  ---------------------------------------------------------
cRecMenuSearchConfirmTimer::cRecMenuSearchConfirmTimer(const cEvent *event, eRecMenuState nextAction) {
    SetWidthPercent(50);
#if VDRVERSNUM >= 20301
    LOCK_CHANNELS_READ;
    const cString channelName = Channels->GetByChannelID(event->ChannelID())->Name();
#else
    const cString channelName = Channels.GetByChannelID(event->ChannelID())->Name();
#endif
    cString message = tr("Timer created");
    cString text = cString::sprintf("%s\n%s\n%s %s - %s\n%s", 
                                    *message, 
                                    *channelName,
                                    *event->GetDateString(),
                                    *event->GetTimeString(),
                                    *event->GetEndTimeString(),
                                    event->Title()
                                );
    cRecMenuItemInfo *infoItem = new cRecMenuItemInfo(*text);
    infoItem->CalculateHeight(width - 2 * border);
    AddMenuItem(infoItem);
    AddMenuItem(new cRecMenuItemButton(tr("OK"), nextAction, true, true));
    CalculateHeight();
    CreatePixmap();
    Arrange();
}

// --- cRecMenuSearchNothingFound  ---------------------------------------------------------
cRecMenuSearchNothingFound::cRecMenuSearchNothingFound(std::string searchString, bool tooShort) {
    SetWidthPercent(50);
    cString text;
    if (!tooShort) {
        cString message = tr("Nothing found for Search String");
        text = cString::sprintf("%s\n\"%s\"", 
                                *message, 
                                searchString.c_str());
    } else {
        cString message = tr("Search String has to have at least three letters");
        text = cString::sprintf("%s\n\"%s\"", 
                                *message, 
                                searchString.c_str());

    }
    cRecMenuItemInfo *infoItem = new cRecMenuItemInfo(*text);
    infoItem->CalculateHeight(width - 2 * border);
    AddMenuItem(infoItem);
    AddMenuItem(new cRecMenuItemButton(tr("OK"), rmsSearchNothingFoundConfirm, true, true));
    CalculateHeight();
    CreatePixmap();
    Arrange();
}

/******************************************************************************************
*   Recording Search Menus
******************************************************************************************/

// --- cRecMenuRecordingSearch  ---------------------------------------------------------
cRecMenuRecordingSearch::cRecMenuRecordingSearch(std::string search) {
    strncpy(searchString, search.c_str(), TEXTINPUTLENGTH);
    SetWidthPercent(60);
    cString infoText = tr("Search in Recordings");
    cRecMenuItemInfo *infoItem = new cRecMenuItemInfo(*infoText, true);
    infoItem->CalculateHeight(width - 2 * border);
    SetHeader(infoItem);
    
    AddMenuItem(new cRecMenuItemText(tr("Search Expression:"), TEXTINPUTLENGTH, false, searchString));
    AddMenuItem(new cRecMenuItemButtonYesNo(tr("Perform Search"), tr("Cancel"), rmsRecordingSearchResult, rmsClose, true));
    CalculateHeight();
    CreatePixmap();
    Arrange();
}

// --- cRecMenuRecordingSearchResults  ---------------------------------------------------------
cRecMenuRecordingSearchResults::cRecMenuRecordingSearchResults(std::string searchString, const cRecording **searchResults, int numResults) {
    this->searchString = searchString;
    this->searchResults = searchResults;
    SetWidthPercent(80);
    cString message1 = tr("Found");
    cString message2 = tr("recording");
    cString message3 = tr("recordings");
    cString message4 = tr("for");
    this->numResults = numResults;
    cString infoText = cString::sprintf("%s %d %s %s:\n\"%s\"", *message1, numResults, (numResults>1)?(*message3):(*message2), *message4, searchString.c_str());
    cRecMenuItem *infoItem = new cRecMenuItemInfo(*infoText, true);
    infoItem->CalculateHeight(width - 2 * border);
    SetHeader(infoItem);
    
    cRecMenuItem *buttons = new cRecMenuItemButtonYesNo(tr("Adapt Search"), tr("Close"), rmsRecordingSearch, rmsClose, false);
    SetFooter(buttons);
    if (searchResults && (numResults > 0)) {
        for (int i = 0; i < numResults; i++) {
            if (!AddMenuItemInitial(new cRecMenuItemRecording(searchResults[i], (i == 0) ? true : false)))
                break;
        }
    }
    CalculateHeight();
    CreatePixmap();
    Arrange();
}

cRecMenuItem *cRecMenuRecordingSearchResults::GetMenuItem(int number) { 
    if ((number >= 0) && (number < numResults)) {
        cRecMenuItem *result = new cRecMenuItemRecording(searchResults[number], false);
        return result;
    }
    return NULL;
}

int cRecMenuRecordingSearchResults::GetTotalNumMenuItems(void) { 
    return numResults;
}

// --- cRecMenuRecordingSearchNotFound  ---------------------------------------------------------
cRecMenuRecordingSearchNotFound::cRecMenuRecordingSearchNotFound(std::string searchString) {
    SetWidthPercent(50);
    cString message = tr("No recordings found for");
    cString text = cString::sprintf("%s\n\"%s\"", 
                                    *message, 
                                    searchString.c_str());
    cRecMenuItemInfo *infoItem = new cRecMenuItemInfo(*text);
    infoItem->CalculateHeight(width - 2 * border);
    AddMenuItem(infoItem);
    AddMenuItem(new cRecMenuItemButton(tr("OK"), rmsClose, true, true));
    CalculateHeight();
    CreatePixmap();
    Arrange();
}

/******************************************************************************************
*   Timeline
******************************************************************************************/

// --- cRecMenuTimeline  ---------------------------------------------------------
cRecMenuTimeline::cRecMenuTimeline(cTVGuideTimerConflicts *timerConflicts) {
    this->timerConflicts = timerConflicts;
    SetStartStop();
    conflictsToday = timerConflicts->GetConflictsBetween(timeStart, timeStop);
    GetTimersForDay();
    SetWidthPercent(95);
    header = new cRecMenuItemTimelineHeader(timeStart, numTimersToday, conflictsToday);
    SetHeader(header);
    cRecMenuItem *footer = new cRecMenuItemButton(tr("Close"), rmsClose, false, true);
    SetFooter(footer);
    SetTimers();
}

void cRecMenuTimeline::SetStartStop(void) {
    time_t now = time(0);
    tm *timeStruct = localtime(&now);
    timeStart = now - timeStruct->tm_hour * 3600 - timeStruct->tm_min * 60 - timeStruct->tm_sec;
    today = timeStart;
    timeStop = timeStart + 24*3600 - 1;
}


void cRecMenuTimeline::GetTimersForDay(void) {
    timersToday.clear();
#if VDRVERSNUM >= 20301
    LOCK_TIMERS_READ;
    const cTimers* timers = Timers;
#else
    const cTimers* timers = &Timers;
#endif
    cSortedTimers SortedTimers(timers);
    int i = 0;
    while (i < SortedTimers.Size()) {
        const cTimer *t = SortedTimers[i];
        if (((t->StartTime() > timeStart) && (t->StartTime() <= timeStop)) || ((t->StopTime() > timeStart) && (t->StopTime() <= timeStop))) {
            if (t->HasFlags(tfActive))
                timersToday.push_back(t);
        }
        i++;
    }
    numTimersToday = timersToday.size();
}

void cRecMenuTimeline::SetTimers(void) {
    ClearMenu();
    if (numTimersToday == 0) {
        AddMenuItem(new cRecMenuItemTimelineTimer(NULL, 0, 0, conflictsToday, header, false));
        header->UnsetCurrentTimer();
        header->SetNumTimersToday(0);
        footer->setActive();
    } else {
        for (int i = 0; i<numTimersToday; i++) {
            cRecMenuItemTimelineTimer *item = new cRecMenuItemTimelineTimer(timersToday[i], timeStart, timeStop, conflictsToday, header, false);
            if (i==0)
                item->setActive();
            if (!AddMenuItemInitial(item))
                break;
            header->SetNumTimersToday(numTimersToday);
        }
        footer->setInactive();
    }
    CalculateHeight();
    CreatePixmap();
    Arrange();
}

void cRecMenuTimeline::PrevDay(void) {
    if ((timeStart - 3600*24) < today)
        return;
    timeStart -= 3600*24;
    timeStop -= 3600*24;
    conflictsToday = timerConflicts->GetConflictsBetween(timeStart, timeStop);
    SetWidthPercent(95);
    header->SetDay(timeStart);
    header->UnsetCurrentTimer();
    header->RefreshTimerDisplay();
    GetTimersForDay();
    SetTimers();
    Display();
}

void cRecMenuTimeline::NextDay(void) {
    timeStart += 3600*24;
    timeStop += 3600*24;
    conflictsToday = timerConflicts->GetConflictsBetween(timeStart, timeStop);
    SetWidthPercent(95);
    header->SetDay(timeStart);
    header->UnsetCurrentTimer();
    header->RefreshTimerDisplay();
    GetTimersForDay();
    SetTimers();
    Display();
}

cRecMenuItem *cRecMenuTimeline::GetMenuItem(int number) { 
    if (number < 0)
        return NULL;
    if (number >= numTimersToday)
        return NULL;
    return new cRecMenuItemTimelineTimer(timersToday[number], timeStart, timeStop, conflictsToday, header, false);
}

int cRecMenuTimeline::GetTotalNumMenuItems(void) { 
    return numTimersToday;
}

void cRecMenuTimeline::ClearMenu(void) {
    InitMenu(true);
    header->UnsetCurrentTimer();
}

const cTimer *cRecMenuTimeline::GetTimer(void) {
    if (cRecMenuItemTimelineTimer *activeItem = dynamic_cast<cRecMenuItemTimelineTimer*>(GetActiveMenuItem()))
        return activeItem->GetTimerValue();
    return NULL;
}


eRecMenuState cRecMenuTimeline::ProcessKey(eKeys Key) {
    eRecMenuState state = rmsContinue;
    switch (Key & ~k_Repeat) {
        case kLeft:
            PrevDay();
            state = rmsConsumed;
            break;
        case kRight:
            NextDay();
            state = rmsConsumed;
            break;
        default:
            break;
    }
    if (state != rmsConsumed) {
        state = cRecMenu::ProcessKey(Key);
    }
    return state;
}

/******************************************************************************************
*   Favorites
******************************************************************************************/

// --- cRecMenuFavorites  ---------------------------------------------------------

cRecMenuFavorites::cRecMenuFavorites(std::vector<cTVGuideSearchTimer> favorites) {
    deleteMenuItems = false;
    this->favorites = favorites;
    CreateFavoritesMenuItems();
    numFavorites = myMenuItems.size();
    SetWidthPercent(70);
    cString header;
    if (numFavorites > 0) {
        header = tr("Favorites");
    } else {
        header = tr("No Favorites available");
    }
    cRecMenuItemInfo *headerItem = new cRecMenuItemInfo(*header, true);
    headerItem->CalculateHeight(width - 2 * border);
    SetHeader(headerItem);

    cRecMenuItem *button = new cRecMenuItemButton(tr("Close"), rmsClose, (numFavorites==0)?true:false);
    SetFooter(button);

    for (int i=0; i<numFavorites; i++) {
        if (i==0)
            myMenuItems[i]->setActive();
        if (!AddMenuItemInitial(myMenuItems[i]))
            break;
    }

    CalculateHeight();
    CreatePixmap();
    Arrange();
}

cRecMenuFavorites::~cRecMenuFavorites(void) {
    for (std::vector<cRecMenuItem*>::iterator it = myMenuItems.begin(); it != myMenuItems.end(); it++) {
        delete *it;
    }
    myMenuItems.clear();
}

void cRecMenuFavorites::CreateFavoritesMenuItems(void) {
    if (config.favWhatsOnNow) {
        myMenuItems.push_back(new cRecMenuItemFavoriteStatic(tr("What's on now"), rmsFavoritesNow, false));
    }
    if (config.favWhatsOnNext) {
        myMenuItems.push_back(new cRecMenuItemFavoriteStatic(tr("What's on next"), rmsFavoritesNext, false));
    }
    if (config.favUseTime1) {
        std::string desc = *cString::sprintf("%s (%s)", config.descUser1.c_str(), NiceTime(config.favTime1).c_str());
        myMenuItems.push_back(new cRecMenuItemFavoriteStatic(desc, rmsFavoritesUser1, false));
    }
    if (config.favUseTime2) {
        std::string desc = *cString::sprintf("%s (%s)", config.descUser2.c_str(), NiceTime(config.favTime2).c_str());
        myMenuItems.push_back(new cRecMenuItemFavoriteStatic(desc, rmsFavoritesUser2, false));
    }
    if (config.favUseTime3) {
        std::string desc = *cString::sprintf("%s (%s)", config.descUser3.c_str(), NiceTime(config.favTime3).c_str());
        myMenuItems.push_back(new cRecMenuItemFavoriteStatic(desc, rmsFavoritesUser3, false));
    }
    if (config.favUseTime4) {
        std::string desc = *cString::sprintf("%s (%s)", config.descUser4.c_str(), NiceTime(config.favTime4).c_str());
        myMenuItems.push_back(new cRecMenuItemFavoriteStatic(desc, rmsFavoritesUser4, false));
    }

    int numAdditionalFavs = favorites.size();
    for (int i = 0; i < numAdditionalFavs; i++) {
        myMenuItems.push_back(new cRecMenuItemFavorite(favorites[i], rmsSearchTimerTest, false));
    }

}

std::string cRecMenuFavorites::NiceTime(int favTime) {
    int hours = favTime/100;
    int mins = favTime - hours * 100;
    return *cString::sprintf("%02d:%02d", hours, mins);
}

cRecMenuItem *cRecMenuFavorites::GetMenuItem(int number) {
    if (number > -1 && number < numFavorites)
        return myMenuItems[number];
    return NULL;
}

int cRecMenuFavorites::GetTotalNumMenuItems(void) {
    return numFavorites;
}

cTVGuideSearchTimer cRecMenuFavorites::GetFavorite(void) {
    cRecMenuItemFavorite *activeItem = dynamic_cast<cRecMenuItemFavorite*>(GetActiveMenuItem());
    return activeItem->GetFavorite();
}
