/*
 * screenshot.c: A plugin for the Video Disk Recorder
 *
 * See the README file for copyright information and how to reach the author.
 *
 */

#include "screenshot.h"
#include <vdr/interface.h>

#include <vdr/status.h>
#include <vdr/recording.h>

#if VDRVERSNUM >= 10307
#include <vdr/skins.h>
#endif

void MakeScreenshot(const char *title, int ShowDate = false, int NewOsd = false) {
  cOsd *osd = NULL;
  const char *Title;
  char fileName[100];
  int i = 0;
  int pnr = 0;
  time_t t = time(NULL);
  struct tm *now = localtime(&t);
  bool isOk = true;
  const cFont *fn;
  char tmp[20];

  if (title)
    Title = title;
  else
    Title = "screenshot";
  // take pictures
  fn = cFont::GetFont(fontSml);
  strftime(tmp, sizeof(tmp), "%Y.%m.%d %H:%M", now);
  if (NewOsd && ShowDate) {
    osd = cOsdProvider::NewOsd(Setup.OSDLeft, Setup.OSDTop);
    tArea Areas[] = { { 0, Setup.OSDHeight - fn->Height(tmp), Setup.OSDWidth - 1, Setup.OSDHeight - 1, 4 } };
    osd->SetAreas(Areas, sizeof(Areas) / sizeof(tArea));
    osd->DrawRectangle(0, Setup.OSDHeight - fn->Height(tmp), Setup.OSDWidth - 1, Setup.OSDHeight - 1, clrTransparent);
  }
  while (isOk && i < iNoOfPics) {
    FILE *fp;
    do {
      pnr++;
      sprintf(fileName, "%s/%s-%d%02d%02d-%03d.%s", sPath, Title, \
    	    now->tm_year + 1900, now->tm_mon + 1, now->tm_mday, \
	    pnr, FILEFORMATS[iFileformat]);
      fp = fopen(fileName, "r");
      if (fp) fclose(fp);
    } while (fp != NULL);
    if (ShowDate) {
      if (NewOsd && ShowDate && osd) {
        osd->DrawText(1, Setup.OSDHeight - fn->Height(tmp), tmp, (tColor)clrWhite, \
          (tColor)clrTransparent, fn);
        osd->Flush();
      } else if (ShowDate) {
#if VDRVERSNUM >= 10307
        cSkinDisplay::Current()->SetMessage(mtInfo, tmp);
        cSkinDisplay::Current()->Flush();
#else
        Interface->Info(tmp);
#endif
      }
    }

#if VDRVERSNUM < 10338
    isOk = cDevice::PrimaryDevice()->GrabImage(fileName, iFileformat, iQuality, iResX, iResY);
#else
    isOk = cDevice::PrimaryDevice()->GrabImageFile(fileName, iFileformat, iQuality, iResX, iResY);
#endif
    i++;
  }
  // show result
  if (isOk)
    isyslog("screenshot: %d image%s saved", iNoOfPics, (iNoOfPics > 1) ? "s" : "");
  else
    esyslog("screenshot: error calling GrabImage(...)");
#if VDRVERSNUM >= 10307
  fn = cFont::GetFont(fontOsd);
  if (isOk) {
    const char *tmp = tr(iNoOfPics > 1 ? "OK - Images saved." : "OK - Image saved.");
    if (osd) {
      osd->DrawRectangle(1, Setup.OSDHeight - fn->Height(tmp), Setup.OSDWidth - 1, \
        Setup.OSDHeight, clrGreen);
      osd->DrawText((Setup.OSDWidth - fn->Width(tmp)) / 2, Setup.OSDHeight - fn->Height(tmp), tmp, \
        (tColor)clrBlack, (tColor)clrGreen, fn);
      osd->Flush();
      cCondWait::SleepMs(2000);
    } else
      Skins.Message(mtInfo, tmp);
      Skins.Flush();
  } else {
    const char *tmp = tr("Error");
    if (osd) {
      osd->DrawRectangle(1, Setup.OSDHeight - fn->Height(tmp), Setup.OSDWidth - 1, \
        Setup.OSDHeight, clrRed);
      osd->DrawText((Setup.OSDWidth - fn->Width(tmp)) / 2, Setup.OSDHeight - fn->Height(tmp), \
        tmp, (tColor)clrBlack, (tColor)clrRed, fn);
      osd->Flush();
      cCondWait::SleepMs(2000);
    } else
      Skins.Message(mtError, tr("Error"));
  }
  if (osd)
    delete osd;
#else
  if (isOk)
    Interface->Info(tr(iNoOfPics > 1 ? "OK - Images saved." : "OK - Image saved."));
  else
    Interface->Error(tr("Error"));
  Interface->Open(0,0);
#endif
  fn = NULL;
}

/*-------------------------------------------------------------------------------------------------
**************** class cMyMenu ********************************************************************
-------------------------------------------------------------------------------------------------*/

cMyMenu::cMyMenu(const char *Title, int ShowDate) {
  title = Title;
  showdate = ShowDate;
}

cMyMenu::~cMyMenu() {
}

void cMyMenu::Show(void) {
  MakeScreenshot(title, showdate, true);
}

/*-------------------------------------------------------------------------------------------------
**************** class cMenuSetupScreenshot *******************************************************
-------------------------------------------------------------------------------------------------*/

void cMenuSetupScreenshot::Store(void) {
  strcpy(sPath, sNewPath);
  iFileformat = iNewFileformat;
  iQuality = iNewQuality;
  iResX = iNewResX;
  iResY = iNewResY;
  iNoOfPics = iNewNoOfPics;
  iHideMenuEntry = iNewHideMenuEntry;
  iHideOsd = iNewHideOsd;
  iShowDate = iNewShowDate;
  SetupStore("Path", sPath);
  SetupStore("Fileformat", iFileformat);
  SetupStore("Quality", iQuality);
  SetupStore("ResX", iResX);
  SetupStore("ResY", iResY);
  SetupStore("NoOfPics", iNoOfPics);
  SetupStore("HideMenuEntry", iHideMenuEntry);
  SetupStore("UserKey", iUserKey);
  SetupStore("HideOsd", iHideOsd);
  SetupStore("ShowDate", iShowDate);
}
  
cMenuSetupScreenshot::cMenuSetupScreenshot(void) {
  strcpy(sNewPath, sPath);
  iNewFileformat = iFileformat;
  iNewQuality = iQuality;
  iNewResX = iResX;
  iNewResY = iResY;
  iNewNoOfPics = iNoOfPics;
  iNewHideMenuEntry = iHideMenuEntry;
  iNewUserKey = iUserKey;
  iNewHideOsd = iHideOsd;
  iNewShowDate = iShowDate;
  char allowedChars[100];
  sprintf(allowedChars, "%s/", tr(FileNameChars));
  Add(new cMenuEditStrItem  (tr("Image directory"),         sNewPath, sizeof(sNewPath), allowedChars));
  Add(new cMenuEditStraItem (tr("Fileformat"),              &iNewFileformat, 2, FILEFORMATS));
  Add(new cMenuEditIntItem  (tr("Image quality (1-100)"),   &iNewQuality, 1, 100));
  Add(new cMenuEditIntItem  (tr("Image width (Pixel)"),     &iNewResX, 1, 768));
  Add(new cMenuEditIntItem  (tr("Image height (Pixel)"),    &iNewResY, 1, 576));
  Add(new cMenuEditIntItem  (tr("No. of pictures to take"), &iNewNoOfPics, 1, 100));
  Add(new cMenuEditBoolItem (tr("Hide mainmenu entry"),     &iNewHideMenuEntry));
//  Add(new cMenuEditIntItem  (tr("User key to use"),         &iNewUserKey, 1, 9));
  Add(new cMenuEditBoolItem (tr("Hide OSD"),                &iNewHideOsd));
  Add(new cMenuEditBoolItem (tr("Show Date"),               &iNewShowDate));
}

/*-------------------------------------------------------------------------------------------------
**************** class cPluginScreenshot **********************************************************
-------------------------------------------------------------------------------------------------*/

cPluginScreenshot::cPluginScreenshot(void) {
  // Initialize any member variables here.
  // DON'T DO ANYTHING ELSE THAT MAY HAVE SIDE EFFECTS, REQUIRE GLOBAL
  // VDR OBJECTS TO EXIST OR PRODUCE ANY OUTPUT!
  title[0] = 0;
}

cPluginScreenshot::~cPluginScreenshot() {
  // Clean up after yourself!
}

const char *cPluginScreenshot::CommandLineHelp(void) {
  // Return a string that describes all known command line options.
  return NULL;
}

bool cPluginScreenshot::ProcessArgs(int argc, char *argv[]) {
  // Implement command line argument processing here if applicable.
  return true;
}

bool cPluginScreenshot::Initialize(void) {
  // Initialize any background activities the plugin shall perform.
  return true;
}

bool cPluginScreenshot::Start(void) {
  // Start any background activities the plugin shall perform.
  RegisterI18n(Phrases);
  // Make dummy picture at startup, because the first screenshot using
  // GrabImage(...) only takes a gray image.
#if VDRVERSNUM < 10338
  cDevice::PrimaryDevice()->GrabImage("/dev/null", false);
#else
  cDevice::PrimaryDevice()->GrabImageFile("/dev/null", false);
#endif
  return true;
}

void cPluginScreenshot::Housekeeping(void) {
  // Perform any cleanup or other regular tasks.
}

cOsdObject *cPluginScreenshot::MainMenuAction(void) {
  if (iHideOsd)
    return new cMyMenu(title, iShowDate);
  else {
    MakeScreenshot(title, iShowDate);
    return NULL;
  }
}

cMenuSetupPage *cPluginScreenshot::SetupMenu(void) {
  // Return a setup menu in case the plugin supports one.
  return new cMenuSetupScreenshot;
}

bool cPluginScreenshot::SetupParse(const char *Name, const char *Value) {
  // Parse your own setup parameters and store their values.
  if       (!strcasecmp(Name, "Path"))          strcpy(sPath, Value);
  else if  (!strcasecmp(Name, "Quality"))       iQuality       = atoi(Value);
  else if  (!strcasecmp(Name, "ResX"))          iResX          = atoi(Value);
  else if  (!strcasecmp(Name, "ResY"))          iResY          = atoi(Value);
  else if  (!strcasecmp(Name, "Fileformat"))    iFileformat    = atoi(Value);
  else if  (!strcasecmp(Name, "NoOfPics"))      iNoOfPics      = atoi(Value);
  else if  (!strcasecmp(Name, "HideMenuEntry")) iHideMenuEntry = atoi(Value);
  else if  (!strcasecmp(Name, "UserKey"))       iUserKey       = atoi(Value);
  else if  (!strcasecmp(Name, "HideOsd"))       iHideOsd       = atoi(Value);
  else if  (!strcasecmp(Name, "ShowDate"))      iShowDate      = atoi(Value);
  else return false;
  return true;
}

void cPluginScreenshot::Replaying(const cControl *Control, const char *Name, const char *filename, bool a) {
  if (Name)
    strncpy(title, Name, sizeof(title));
  else
    strcpy(title, "screenshot");
  while (char *s= strchr(title, '/'))
    s[0] = '-';
}

/*
void cPluginScreenshot::ChannelSwitch(const cDevice *Device, int ChannelNumber) {
  if (ChannelNumber && Device->IsPrimaryDevice())
    strncpy(title, (Channels.GetByNumber(ChannelNumber))->Name(), sizeof(channelName));
}
*/

void cPluginScreenshot::OsdProgramme(time_t PresentTime, const char *PresentTitle, \
  const char *PresentSubtitle, time_t FollowingTime, const char *FollowingTitle, \
  const char *FollowingSubtitle) {
  if (PresentTitle)
    strncpy(title, PresentTitle, sizeof(title));
  else
    strcpy(title, "screenshot");
  while (char *s= strchr(title, '/'))
    s[0] = '-';
}

VDRPLUGINCREATOR(cPluginScreenshot); // Don't touch this!
