/*
 * Taken For Telecable From
 *
 * Softcam plugin to VDR (C++)
 *
 * This code 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 code 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
 */



#include <getopt.h>
#include <stdlib.h>
#include <unistd.h>
#include <vdr/interface.h>
#include <vdr/plugin.h>
#include <vdr/menuitems.h>
#include <vdr/status.h>

#include "opts.h"  // From Sc plugin 
#include "telecable.h"

extern char ** UrlDescriptorList;
extern cPluginTelecable * thePluginTelecable;


/*
// --- cMenuEditCapItem --------------------------------------------------------
class cMenuEditCapItem : public cMenuEditIntItem {
private:
  const cCaDefinition *ca;
protected:
  virtual void Set(void);
public:
  cMenuEditCapItem(const char *Name, int *Value);
  eOSState ProcessKey(eKeys Key);
  };

cMenuEditCapItem::cMenuEditCapItem(const char *Name, int *Value)
:cMenuEditIntItem(Name, Value, 0)
{
  ca=CaDefinitions.Get(*Value);
  Set();
}

void cMenuEditCapItem::Set(void)
{
  if(ca) SetValue(ca->Number() ? ca->Description():tr("off"));
  else   cMenuEditIntItem::Set();
}

eOSState cMenuEditCapItem::ProcessKey(eKeys Key)
{
  eOSState state = cMenuEditItem::ProcessKey(Key);
  if (state == osUnknown) {

     if(NORMALKEY(Key)==kLeft || NORMALKEY(Key)==kRight) {
       }
     else return cMenuEditIntItem::ProcessKey(Key);
     Set();
     state=osContinue;
     }
  return state;
}
*/

// --- cOpt --------------------------------------------------------------------

cOpt::cOpt(const char *Name, const char *Title)
{
  name=Name; title=Title;
  fullname=0; persistant=true;
}

cOpt::~cOpt()
{
  free(fullname);
}

const char *cOpt::FullName(const char *PreStr)
{
  if(PreStr) {
    free(fullname);
    asprintf(&fullname,"%s.%s",PreStr,name);
    return fullname;
    }
  else return name;
}

// --- cOptInt -----------------------------------------------------------------

cOptInt::cOptInt(const char *Name, const char *Title, int *Storage, int Min, int Max)
:cOpt(Name,Title)
{
  storage=Storage; 
  min=Min; 
  max=Max;
}

void cOptInt::Parse(const char *Value)
{
  *storage=atoi(Value);
}

void cOptInt::Backup(void)
{
  value=*storage;
}

bool cOptInt::Set(void)
{
  if(value!=*storage) { *storage=value; return true; }
  return false;
}

void cOptInt::Store(const char *PreStr)
{
  thePluginTelecable->SetupStore(FullName(PreStr),*storage);
 }

void cOptInt::Create(cOsdMenu *menu)
{
  menu->Add(new cMenuEditIntItem(tr(title),&value,min,max));
}

// --- cOptSel -----------------------------------------------------------------

cOptSel::cOptSel(const char *Name, const char *Title, int *Storage, int NumStr, const char * const *Strings)
:cOptInt(Name,Title,Storage,0,NumStr)
{
  strings=Strings;
  trStrings=0;
}

cOptSel::~cOptSel()
{
  free(trStrings);
}

void cOptSel::Create(cOsdMenu *menu)
{

    menu->Add(new cMenuEditStraItem(tr(title),&value, max , strings));
}

// --- cOptSite -----------------------------------------------------------------

cOptSite::cOptSite(const char *Name, const char *Title, int *Storage, int NumStr, const char * const *Strings)
:cOptInt(Name,Title,Storage,0,NumStr)
{
  strings=Strings;
  trStrings=0;
}

cOptSite::~cOptSite()
{
  free(trStrings);
}

void cOptSite::Create(cOsdMenu *menu)
{

    menu->Add(new cMenuEditStraItem(tr(title),&value,MAX_URL_ITEMS ,UrlDescriptorList));
}


// --- cOptBool -----------------------------------------------------------------

cOptBool::cOptBool(const char *Name, const char *Title, int *Storage)
:cOptInt(Name,Title,Storage,0,1)
{}

void cOptBool::Create(cOsdMenu *menu)
{
  menu->Add(new cMenuEditBoolItem(tr(title),&value));
}

// --- cOptStr -----------------------------------------------------------------

cOptStr::cOptStr(const char *Name, const char *Title, char *Storage, int Size, const char *Allowed)
:cOpt(Name,Title)
{
  storage=Storage; size=Size; allowed=Allowed;
  value=MALLOC(char,size);
}

cOptStr::~cOptStr()
{
  free(value);
}

void cOptStr::Parse(const char *Value)
{
  strn0cpy(storage,Value,size);
}

void cOptStr::Backup(void)
{
  strn0cpy(value,storage,size);
}

bool cOptStr::Set(void)
{
  if(strcmp(value,storage)) { strn0cpy(storage,value,size); return true; }
  return false;
}

void cOptStr::Store(const char *PreStr)
{
  thePluginTelecable->SetupStore(FullName(PreStr),storage);
}

void cOptStr::Create(cOsdMenu *menu)
{
  menu->Add(new cMenuEditStrItem(tr(title),value,size,allowed));
}


// --- cOptCap -----------------------------------------------------------------
/*
class cOptCap : public cOpt {
protected:
  int *storage, *value;
  int size, disp, len;
public:
  cOptCap(const char *Name, const char *Title, int *Storage, int Size, int Disp);
  virtual ~cOptCap();
  virtual void Parse(const char *Value);
  virtual void Backup(void);
  virtual bool Set(void);
  virtual void Store(const char *PreStr);
  virtual void Create(cOsdMenu *menu);
  };

cOptCap::cOptCap(const char *Name, const char *Title, int *Storage, int Size, int Disp)
:cOpt(Name,Title)
{
  storage=Storage; size=Size; disp=Disp; len=sizeof(int)*size;
  value=MALLOC(int,size);
}

cOptCap::~cOptCap()
{
  free(value);
}

void cOptCap::Parse(const char *Value)
{
  memset(storage,0,len);
  int i=0;
  while(1) {
    char *p;
    const int c=strtol(Value,&p,10);
    if(c<=0 || p==Value || i>=size) return;
    storage[i++]=c;
    Value=p;
    }
}

void cOptCap::Backup(void)
{
  memcpy(value,storage,len);
}

bool cOptCap::Set(void)
{
  if(memcmp(value,storage,len)) { memcpy(storage,value,len); return true; }
  return false;
}

void cOptCap::Store(const char *PreStr)
{
  char b[256];
  for(int i=0,p=0; i<size; i++)
    if(storage[i]) p+=snprintf(b+p,sizeof(b)-p,"%d ",storage[i]);
  thePluginTelecable->SetupStore(FullName(PreStr),b);
}

void cOptCap::Create(cOsdMenu *menu)
{

  for(int i=0; i<disp; i++) {
    char buff[32];
    snprintf(buff,sizeof(buff),"%s %d",tr(title),i+1);
    menu->Add(new cMenuEditCapItem(buff,&value[i]));
    }

}
*/

// --- cOpts -------------------------------------------------------------------

cOpts::cOpts(const char *PreStr, int NumOpts)
{
  preStr=PreStr;
  numOpts=NumOpts; numAdd=0;
  if((opts=MALLOC(cOpt *,numOpts))) memset(opts,0,sizeof(cOpt *)*numOpts);
}

cOpts::~cOpts()
{
  if(opts) {
    for(int i=0; i<numOpts; i++) delete opts[i];
    free(opts);
    }
}

void cOpts::Add(cOpt *opt)
{
  if(opts && numAdd<numOpts) opts[numAdd++]=opt;
}

bool cOpts::Parse(const char *Name, const char *Value)
{
  if(opts) {
    for(int i=0; i<numAdd; i++)
      if(opts[i] && opts[i]->Persistant() && !strcasecmp(Name,opts[i]->Name())) {
        opts[i]->Parse(Value);
        return true;
        }
    }
  return false;
}

bool cOpts::Store(void)
{
  bool res=false;
  if(opts) {
    for(int i=0; i<numAdd; i++)
      if(opts[i]) {
        if(opts[i]->Set()) res=true;
        if(opts[i]->Persistant()) opts[i]->Store(preStr);
        }
    }
  return res;
}

void cOpts::Backup(void)
{
  if(opts) {
    for(int i=0; i<numAdd; i++)
      if(opts[i]) opts[i]->Backup();
    }
}

void cOpts::Create(cOsdMenu *menu)
{
  if(opts) {
    for(int i=0; i<numAdd; i++)
      if(opts[i]) opts[i]->Create(menu);
    }
}
