/*
 * menu.c: OSD menu
 *
 * PhotoCD Player plugin for VDR (the Video Disk Recorder)
 * Copyright (C) 2002  Thomas Heiligenmann  <thomas@heiligenmann.de>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA
 *
 */


#include <stdio.h>
#include <typeinfo>
#include <vdr/interface.h>
#include <vdr/status.h>
#include "i18n.h"
#include "menu.h"


// --- cPcdControl -----------------------------------------------------------

class cPcdControl : cPcdViewerControl {
private:
  bool visible, modeOnly;
  static int image;
  static cPCD *pcd;
public:
  cPcdControl(void);
  virtual ~cPcdControl();
  virtual eOSState ProcessKey(eKeys Key);
  virtual void Hide(void);
  static void SetImage(int Image, cPCD *Pcd);
};

int cPcdControl::image = 0;
cPCD *cPcdControl::pcd = 0;

cPcdControl::cPcdControl(void)
: cPcdViewerControl(image, pcd)
{
  visible = modeOnly = false;
}

cPcdControl::~cPcdControl()
{
  cStatus::MsgReplaying(this, NULL, NULL, true);
  Stop();
}

void cPcdControl::SetImage(int Image, cPCD *Pcd)
{
  cControl *control = cControl::Control();
  if (control && typeid(*control)==typeid(cPcdControl)) {
     static_cast<cPcdControl*>(control)->GotoImage(Image);
     return;
  }

  image = Image;
  pcd = Pcd;
  cControl::Launch(new cPcdControl);
}

void cPcdControl::Hide(void)
{
  if (visible) {
#if APIVERSNUM >= 10500
     SetNeedsFastResponse(false);
#else
     needsFastResponse = false;
#endif
     visible = false;
     modeOnly = false;
  }
}

eOSState cPcdControl::ProcessKey(eKeys Key)
{
  if (!Active())
     return osEnd;
  switch (Key) {
     case k0:      ToggleSlideshow(); break;
     // Zooming:
     case k1:      ZoomImage(-1); break;
     case k2:      ZoomImage(0);  break;
     case k3:      ZoomImage(1);  break;
     // Panning:
     case kLeft:   PanImage(-1, 0, 0); break;
     case kRight:  PanImage(1, 0, 0);  break;
     case kUp:     PanImage(0, -1, 0); break;
     case kDown:   PanImage(0, 1, 0);  break;
     case k5:      PanImage(0, 0, 1);  break;
     // Positioning:
     case k4:      SkipImages(-1); break;
     case k6:      SkipImages(1);  break;
     case kBlue:   Hide();
                   Stop();
                   pcd->Close();
                   return osEnd;
     default: {
        switch (Key) {
           // Editing: (?)
           default: {
              switch (Key) {
                 // Menu control:
                 case kOk:   break;
                 case kBack: pcd->Close();
                             return osEnd;
                 default:    return osUnknown;
              }
           }
        }
     }
  }
  return osContinue;
}


// --- cPcdMenuItem ----------------------------------------------------------

class cPcdMenuItem : public cOsdItem {
private:
  int image;
public:
  cPcdMenuItem(int Image, int lba, int len);
  int Image(void) { return image; }
};

cPcdMenuItem::cPcdMenuItem(int Image, int lba, int len)
{
  image = Image;
  char *buffer = NULL;
#ifdef DEBUG_PCD
  asprintf(&buffer, "Image %03d  %d  %d", image+1, lba, len);
#else
  asprintf(&buffer, "Image %03d", image+1);
#endif //DEBUG_PCD
  SetText(buffer, false);
}


// --- cPcdMenu --------------------------------------------------------------

cPcdMenu::cPcdMenu(cPCD *Pcd)
: cOsdMenu(tr("PhotoCD"))
{
  pcd = Pcd;
  if (pcd->getPCD() && pcd->DiscOk()) {
     pcd->Open();
     if (pcd->VerifyPCD()) {
        dsyslog("PCD: %d Images", pcd->GetImageCount());
        for (int i=0; i<pcd->GetImageCount(); i++)
           Add(new cPcdMenuItem(i, pcd->Image[i].lba, pcd->Image[i+1].lba-pcd->Image[i].lba));
     } else
        Add(new cOsdItem(tr("No PhotoCD detected")));
  } else
     Add(new cOsdItem(tr("No disc inserted")));
  SetHelp(
     pcd->VerifyPCD() ? tr("Key$Play") : NULL,
     NULL,
     pcd->DiscOk() ? tr("Eject") : NULL,
     NULL
  );
  Display();
}

cPcdMenu::~cPcdMenu()
{
}

eOSState cPcdMenu::Play(void)
{
  if (pcd->VerifyPCD() && pcd->GetImageCount()>0) {
     cPcdMenuItem *mpi = (cPcdMenuItem*)Get(Current());
     if (mpi) {
        cPcdControl::SetImage(mpi->Image(), pcd);
        dsyslog("PCD: Play Image %d", mpi->Image()+1);
        return osEnd;
     }
  }
  return osContinue;
}

eOSState cPcdMenu::Eject(void)
{
  if (pcd->DiscOk()) {
     pcd->Close();
     dsyslog("PCD: Eject");
     pcd->Eject();
     return osStopReplay;
  }
  return osContinue;
}

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

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