///////////////////////////////////////////////////
// activy3xx LCD plugin for VDR
//
// Original written by:
//
// Meinrad Sauter <meinrad.sauter@gmx.de>
// andreas 'randy' weinberger <vdr@smue.org>
//
// rearranged, beautified and rewritten by:
//
// Markus Geisler <geisler@primusnetz.de>
//
// optimized by:
// Sascha Quint <sascha.quint@gmx.net>
//
// rearranged, beautified and rewritten by:
// Helmut Auer <helmut@helmutauer.de>
//
///////////////////////////////////////////////////////////

#ifndef __ALCD_CPP
#define __ALCD_CPP

#include <getopt.h>
#include <stdlib.h>
#include "alcd-thread.h"
#include <vdr/status.h>
#include <vdr/plugin.h>

// Statische Variablen
static const char *VERSION        = "1.3.0";
static const char *DESCRIPTION    = tr("Activy3xx LCD-Plugin");
static const char *MAINMENUENTRY  = NULL;

#include "alcd.h"

#define SETUP_SLEEPTIME           "Sleeptime"
#define SETUP_SCROLLSPEED         "ScrollSpeed"
#define SETUP_SCROLLING           "Scrolling"
#define SETUP_UMLAUTS             "Umlauts"
#define SETUP_LEDRECORD           "LEDRecord"
#define SETUP_LCDBRIGHTNESS       "LCDBrightness"
#define SETUP_LCDAVAILABLE        "LCDavailable"
#define SETUP_LCDBRIGHTNESSONEXIT "LCDBrightnessOnExit"
#define SETUP_PROGRESS            "ProgressSign"
#define SETUP_MSGTIME             "MessageTime"
#define SETUP_ALIGNMENT           "Alignment"
#define PROGRESS_SIGNS            "*#>|oO0X"

char *resetScript = "/etc/init.d/activy.sh";

// sonstige Variablen
unsigned int ScrollSpeed = 3;
bool Umlauts = false;              // Show Umlauts
int Scrolling = SCROLL_BLOCK;      // Kind of scrolling
int LEDRecord = LEDREC_GREEN;      // Message LED
int LCDBrightness = BRIGHTEST;     // Brightness 0 == bright, 4 == dark...
int LCDBrightnessOnExit = DARKEST;
int Alignment = ALIGN_CENTER;
bool LCDavailable = true;
int MsgTime = 5;
int SleepTime = 10;
char ProgChar = '#';

///////////////////////////////////////////////////////////
// Class cPluginAlcd Member Implementations

cPluginAlcd::cPluginAlcd(void)
{
   // Initialize any member varaiables here.
   // DON'T DO ANYTHING ELSE THAT MAY HAVE SIDE EFFECTS, REQUIRE GLOBAL
   // VDR OBJECTS TO EXIST OR PRODUCE ANY OUTPUT!
   aLcd = NULL;
}

cPluginAlcd::~cPluginAlcd()
{
   // Clean up after yourself!
   delete aLcd;
}

const char *cPluginAlcd::CommandLineHelp(void)
{
   // Return a string that describes all known command line options.
   static char *help_str=0;

   free( help_str );
   asprintf( &help_str, "  -r <file>,  --resetscript=<file>  script to execute after pic reset\n"
             "            (usually something like /etc/init.d/activy.sh)\n" );
   return help_str;
}

bool cPluginAlcd::ProcessArgs(int argc, char *argv[])
{
   // Implement command line argument processing here if applicable.
   static struct option long_options[] = {
      { "resetscript", required_argument, NULL, 'r'},
      { NULL}};

   int c, option_index = 0;

   while( ( c = getopt_long( argc, argv, "r:", long_options, &option_index ) ) != -1 ) {
      switch( c ) {
         case 'r':  resetScript = optarg; break;
         default:  return false;
      }
   }

   return true;
}

bool cPluginAlcd::Start(void)
{
//     	isyslog("Calling cPluginAlcd::Start");
   // Start any background activities the plugin shall perform.
   aLcd = new cLCD();
   aLcd->Start();
   return true;
}

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

cOsdMenu *cPluginAlcd::MainMenuAction(void)
{
   // Perform the action when selected from the main VDR menu.
   return NULL;
}


///////////////////////////////////////////////////////////
// Class cMenuSetupAlcd Member Implementations

cMenuSetupAlcd::cMenuSetupAlcd(void) 
{
   static const char *LEDRec[2];
   LEDRec[LEDREC_RED] = tr("upper LED blinking");
   LEDRec[LEDREC_GREEN] = tr("lower LED");

   static const char *Scroll[2];
   Scroll[SCROLL_BLOCK] = tr("By block");
   Scroll[SCROLL_CHAR] = tr("By character");

   static const char *OnOff[2];
   OnOff[0] = tr("off");
   OnOff[1] = tr("on");

   static const char *Aligntext[3];
   Aligntext[0] = tr("center");
   Aligntext[1] = tr("left");
   Aligntext[2] = tr("right");

   newScrollSpeed = ScrollSpeed;
   newSleepTime = SleepTime;
   newScrolling = Scrolling;
   newMsgTime = MsgTime;
   newUmlauts = Umlauts;
   newLEDRecord = LEDRecord;
   newLCDBrightness = LCDBrightness;
   newLCDBrightnessOnExit = LCDBrightnessOnExit;
   newProgChar = ProgChar;
   newAlignment = Alignment;

   Add(new cMenuEditStraItem( tr("Record LED"),  &newLEDRecord, 2, LEDRec));
   Add(new cMenuEditBoolItem( tr("Display available"), (int *)&LCDavailable ));
   Add(new cMenuEditIntItem( tr("Sleeptime in deciseconds"), &newSleepTime, 1, 100));
   Add(new cMenuEditIntItem( tr("Message display (in seconds)"), &newMsgTime, 1, 9999));
   Add(new cMenuEditIntItem( tr("Scroll speed (factor of Sleeptime)"), &newScrollSpeed, 0, 100));
   Add(new cMenuEditStraItem( tr("Scroll behaviour"),  &newScrolling, 2, Scroll));
   Add(new cMenuEditStraItem( tr("Umlauts"),  &newUmlauts, 2, OnOff));
   Add(new cMenuEditStraItem( tr("Alignment"),  &newAlignment, 3, Aligntext));
   Add(new cMenuEditIntItem( tr("Display Brightness"), &newLCDBrightness, OFF, BRIGHTEST));
   Add(new cMenuEditIntItem( tr("Display Brightness on exit"), &newLCDBrightnessOnExit, OFF, BRIGHTEST));
   Add(new cMenuEditChrItem( tr("Progress Sign"), &newProgChar, (const char *)PROGRESS_SIGNS));
}

void cMenuSetupAlcd::Store(void)
{
   SetupStore(SETUP_SLEEPTIME, SleepTime = newSleepTime);
   SetupStore(SETUP_SCROLLSPEED, ScrollSpeed = newScrollSpeed);
   SetupStore(SETUP_SCROLLING, Scrolling = newScrolling);
   SetupStore(SETUP_UMLAUTS, Umlauts = newUmlauts);
   SetupStore(SETUP_LEDRECORD, LEDRecord = newLEDRecord);
   SetupStore(SETUP_LCDBRIGHTNESS, LCDBrightness = newLCDBrightness);
   SetupStore(SETUP_LCDAVAILABLE, LCDavailable);
   SetupStore(SETUP_ALIGNMENT, Alignment = newAlignment);
   SetupStore(SETUP_LCDBRIGHTNESSONEXIT, LCDBrightnessOnExit = newLCDBrightnessOnExit);
   SetupStore(SETUP_PROGRESS, ProgChar = newProgChar);
   SetupStore(SETUP_MSGTIME, MsgTime = newMsgTime);
}

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

bool cPluginAlcd::SetupParse(const char *Name, const char *Value)
{
   // Parse your own setup parameters and store their values.
   if( !strcasecmp(Name, SETUP_SCROLLSPEED) )
      ScrollSpeed = atoi(Value);
   else if( !strcasecmp(Name, SETUP_SLEEPTIME) )
      SleepTime = atoi(Value);
   else if( !strcasecmp(Name, SETUP_MSGTIME) )
      MsgTime = atoi(Value);
   else if( !strcasecmp(Name, SETUP_LEDRECORD) )
      LEDRecord = atoi(Value);
   else if( !strcasecmp(Name, SETUP_UMLAUTS) )
      Umlauts = atoi(Value);
   else if( !strcasecmp(Name, SETUP_ALIGNMENT) )
      Alignment = atoi(Value);
   else if( !strcasecmp(Name, SETUP_SCROLLING) )
      Scrolling = atoi(Value);
   else if( !strcasecmp(Name, SETUP_LCDBRIGHTNESS) )
      LCDBrightness = atoi(Value);
   else if( !strcasecmp(Name, SETUP_LCDAVAILABLE) )
      LCDavailable = atoi(Value);
   else if( !strcasecmp(Name, SETUP_LCDBRIGHTNESSONEXIT) )
      LCDBrightnessOnExit = atoi(Value);
   else if( !strcasecmp(Name, SETUP_PROGRESS) )
      ProgChar = (char)atoi(Value);
   else
      return false;

   return true;
}

const char **cPluginAlcd::SVDRPHelpPages(void)
{
   static const char *HelpPages[] = {
      "LOCK\n"
      "    stop vdr mode.",
      "UNLOCK\n"
      "    start vdr mode.",
      "SHOW <text>\n"
      "    display text.",
      "LED [OFF OFF|OFF ON|ON OFF|ON ON]\n"
      "    set LED's.",
      "PWRLED [BLINK|GREEN|RED]\n"
      "    set PowerLED.",
      "STAY [ON|OFF]\n"
      "    let Text stay after shutdown.",
      NULL
   };
   return HelpPages;
}

cString cPluginAlcd::SVDRPCommand(const char *Command, const char *Option, int &ReplyCode)
{
   if( !strcasecmp(Command, "LOCK") ) {
      aLcd->Lock( true );
      return cString::sprintf("Display is locked");
   }
   else if( !strcasecmp(Command, "UNLOCK") ) {
      aLcd->Lock( false );
      return cString::sprintf("Display is unlocked");
   }
   else if( !strcasecmp(Command, "SHOW") ) {
      aLcd->SetText(Option);
      return cString::sprintf("String written to Display");
   }
   else if( !strcasecmp(Command, "LED") && Option != NULL ) {
      if( !strcasecmp(Option, "OFF OFF") ) {
         aLcd->SetLED(false,false);
      }
      else if( !strcasecmp(Option, "OFF ON") ) {
         aLcd->SetLED(false,true);
      }
      else if( !strcasecmp(Option, "ON OFF") ) {
         aLcd->SetLED(true,false);
      }
      else if( !strcasecmp(Option, "ON ON") ) {
         aLcd->SetLED(true,true);
      }
      else {
         return cString::sprintf("Invalid Option for LED");
      }
      return cString::sprintf("LED set");
   }
   else if( !strcasecmp(Command, "PWRLED") && Option != NULL ) {
      if( !strcasecmp(Option, "BLINK") ) {
         aLcd->SetPowerLED(PWRLED_BLINK);
      }
      else if( !strcasecmp(Option, "GREEN") ) {
         aLcd->SetPowerLED(PWRLED_GREEN);
      }
      else if( !strcasecmp(Option, "RED") ) {
         aLcd->SetPowerLED(PWRLED_RED);
      }
      else {
         return cString::sprintf("Invalid Option for PWRLED");
      }
      return cString::sprintf("PWRLED set");
   }
   else if( !strcasecmp(Command, "STAY") && Option != NULL ) {
      if( !strcasecmp(Option, "ON") ) {
         aLcd->SetTextPermanent(true);
      }
      else if( !strcasecmp(Option, "OFF") ) {
         aLcd->SetTextPermanent(false);
      }
      else {
         return cString::sprintf("Invalid Option for STAY");
      }
      return cString::sprintf("STAY Option set to %s", Option);
   }
   return NULL;
}


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

#endif
