#include "player.h"
#include "common.h"
#include <fmp.h>

class cPlayerEm84xx: public cPlayer {
   friend DWORD PlayerCallback(DWORD dwContext, DWORD dwMsg, DWORD dwValue);

private:
   enum em84PlayState {
      psDVDMenu,
      psDVDTitle
   };

   bool          mActive;
   em84PlayState mState;
   bool          mPlay, mForward;
   int           mSpeed;

protected:
   virtual void Activate(bool On);

   void Play(void);
   void Pause(void);
   void Forward(void);
   void Rewind(void);

public:
   cPlayerEm84xx(void);
   virtual ~cPlayerEm84xx();

   virtual bool GetIndex(int &Current, int &Total, bool SnapToIFrame = false);
   virtual bool GetReplayMode(bool &Play, bool &Forward, int &Speed);

   eOSState ProcessKey(eKeys Key);
};


DWORD PlayerCallback(DWORD dwContext, DWORD dwMsg, DWORD dwValue)
{
   //Dprintf("CB: Context=%lu, Msg=%lx, Value=%lu\n", dwContext, dwMsg, dwValue);
   cPlayerEm84xx *This = (cPlayerEm84xx*)dwContext;
   if (dwMsg == FMPM_DVD_DOMAIN_CHANGE) {
      //Dprintf("Change to menu\n");
      This->mState = cPlayerEm84xx::psDVDMenu;
   }
   else if (dwMsg == FMPM_DVD_CURRENT_TIME) {
      //Dprintf("change to title\n");
      This->mState = cPlayerEm84xx::psDVDTitle;
   }
   return FMPE_OK;
}

cPlayerEm84xx::cPlayerEm84xx(void):
cPlayer(pmExtern_THIS_SHOULD_BE_AVOIDED),
mActive(false),
mState(psDVDMenu),
mPlay(true),
mForward(true),
mSpeed(-1)
{
   Dprintf("%s\n", __PRETTY_FUNCTION__);
}

cPlayerEm84xx::~cPlayerEm84xx()
{
   Dprintf("%s\n", __PRETTY_FUNCTION__);
   Detach();
}

void cPlayerEm84xx::Activate(bool On)
{
   Dprintf("%s(%s)\n", __PRETTY_FUNCTION__, On ? "true" : "false");
   if (On) {
      FMPLoadDisc();
      if (FMPIsDiscLoaded()) {
         FMP_OPENSTRUCT os;
         os.dwStructSize = sizeof(FMP_OPENSTRUCT);
         os.dwFlags = FMPF_DISCPLAYBACK;
         os.dwSize = KILOBYTE(32);
         os.dwCount = 10;
         os.pCallback = PlayerCallback;
         os.dwContext = (DWORD)this;
         os.bDriverNumber = 0;
         os.sFileName = NULL;
         os.bFileSystem = DONTCARE_ACCESS;
         FMPOpenDiscPlayback(&os);
         //mDiscType = os.bDiscContent;
         //Dprintf("type = %lu\n", mDiscType);
         FMPSet(FMPI_VIDEOOUT, FMPV_VIDEOOUT_COMPOSITE | FMPV_VIDEOOUT_TV |
                FMPV_VIDEOOUT_PAL);
         cDevice::PrimaryDevice()->SetVolume(cDevice::CurrentVolume(), true);
         FMPPlay();
         mActive = true;
      }
   }
   else {
      FMPStop();
      FMPClose();
      mActive = false;
   }
}

bool cPlayerEm84xx::GetIndex(int &Current, int &Total, bool SnapToIFrame)
{
   Current = FMPGet(FMPI_CURRENT_TIME) * FRAMESPERSEC;
   Total = FMPGet(FMPI_TOTAL_TITLE_TIME) * FRAMESPERSEC;
   return true;
}

bool cPlayerEm84xx::GetReplayMode(bool &Play, bool &Forward, int &Speed)
{
   Play = mPlay;
   Forward = mForward;
   Speed = mSpeed;
   return true;
}

void cPlayerEm84xx::Play(void)
{
   Dprintf("play, play=%d, speed=%d\n", mPlay, mSpeed);
   if (!mPlay || mSpeed != -1) {
      if (mPlay && mSpeed >= 0) {
         if (mForward)
            ForwardScan(0, TRUE);
         else
            BackwardScan(0, TRUE);
      }

      FMPPlay();
      Dprintf("fmpplay\n");
      mPlay = true;
      mForward = true;
      mSpeed = -1;
   }
}

void cPlayerEm84xx::Pause(void)
{
   if (mPlay) {
      if (mSpeed >= 0) {
         if (mForward)
            ForwardScan(0, TRUE);
         else
            BackwardScan(0, TRUE);
      }
      FMPPause();
      mPlay = false;
      mForward = true;
      mSpeed = -1;
   }
   else
      Play();
}

void cPlayerEm84xx::Forward(void)
{
   if (mPlay) { // Fast Forward
      ForwardScan(6, TRUE);
      mForward = true;
      mSpeed = 0;
   }
}

void cPlayerEm84xx::Rewind(void)
{
   if (mPlay) { // Fast Rewind
      BackwardScan(6, TRUE);
      mForward = false;
      mSpeed = 0;
   }
}

eOSState cPlayerEm84xx::ProcessKey(eKeys Key)
{
   if (!mActive) return osEnd;

   switch (Key) {
      case kUp:      if (mState == psDVDMenu) {
            UpperButtonSelect(); break;
         }
      case kDown:    if (mState == psDVDMenu) {
            LowerButtonSelect(); break;
         }
      case kLeft:    if (mState == psDVDMenu) {
            LeftButtonSelect(); break;
         }
      case kRight:   if (mState == psDVDMenu) {
            RightButtonSelect(); break;
         }

      case kPlay:    Play();
         break;

      case kPause:   Pause();
         break;

      case kFastRew: Rewind();
         break;

      case kFastFwd: Forward();
         break;

      case kOk:      if (mState == psDVDMenu) {
            ButtonActivate(); break;
         }
         else return osUnknown;
         break;

      case kRed   :  MenuCall(DVD_ROOT_ID);
         break;

/*if (mState == psDVDMenu) break;
                  mZoomStep = (mZoomStep + 1) % ZoomStepCount;
               Dprintf("zoomstep: %d\n", mZoomStep);
           if(mZoomStep == 0)
            ;//FMPSet(FMPI_OVERLAY_FLAGS,0x0002);
          else
            ;//FMPSet(FMPI_OVERLAY_FLAGS,0x0001);
                  FMPSetVisibleSource(ZoomSteps[mZoomStep].x1, ZoomSteps[mZoomStep].y1,
                                      ZoomSteps[mZoomStep].x2, ZoomSteps[mZoomStep].y2);*/

      case kYellow:
      case kGreen:
      case kBlue:
         break;

      case kStop:
      case kBack:    return osEnd;

      default:       break;
   }

   return osContinue;

   /*case kRed:
     MenuCall(DVD_ROOT_ID);
   break;

   case kYellow:
     FMPSetVisibleSource(0,0,360,288);
   break;

   default:
     return osUnknown;
   break;
}

return osContinue;*/
}

cControlEm84xx::cControlEm84xx(void):
cControl(mPlayer = new cPlayerEm84xx),
mDisplay(NULL)
{
   Dprintf("%s\n", __PRETTY_FUNCTION__);
}

cControlEm84xx::~cControlEm84xx()
{
   Dprintf("%s\n", __PRETTY_FUNCTION__);
   Hide();
   delete mPlayer;
}

void cControlEm84xx::Hide(void)
{
   Dprintf("%s\n", __PRETTY_FUNCTION__);
   DELETENULL(mDisplay);
}

void cControlEm84xx::ShowProgress(bool Open)
{
   if (mDisplay == NULL && Open) {
      mDisplay = Skins.Current()->DisplayReplay(false);
      if (mDisplay == NULL)
         return;
      mDisplay->SetTitle("DVD");
   }

   if (mDisplay != NULL) {
      bool play, forward;
      int speed, current, total;
      if (mPlayer->GetReplayMode(play, forward, speed))
         mDisplay->SetMode(play, forward, speed);
      if (mPlayer->GetIndex(current, total)) {
         mDisplay->SetProgress(current, total);
         mDisplay->SetCurrent((const char*)IndexToHMSF(current));
         mDisplay->SetTotal((const char*)IndexToHMSF(total));
      }
   }
}

eOSState cControlEm84xx::ProcessKey(eKeys Key)
{
   //Dprintf("%s\n", __PRETTY_FUNCTION__);

   eOSState state = mPlayer->ProcessKey(Key);
   switch (state) {
      case osEnd:
         Hide(); return osEnd;

      case osUnknown:
         switch (Key) {
            case kOk:    if (mDisplay == NULL) ShowProgress(true);
               else Hide();
               return osContinue;

            default: break;
         }
         break;

      default:
         break;
   }

   ShowProgress();
   return state;

   /*switch (Key) {

   case kStop:
   case kBlue:
   case kBack:
      Hide();
      return osEnd;

   case kOk:
      if (mDisplay == NULL)
         ShowProgress(true);
      else
         Hide();
      break;

   default:
      break;
   }*/

   //ShowProgress();

   //return osContinue;
}
