#include <stdlib.h>
#include <stdio.h>
#include <string.h>
//#include <../main.h>
#include <vdr/tools.h>
#include "opts.h"



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);
    fullname=new char[1024];
    sprintf(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)
{
     /*TODO add ini saving code here*/
//  ScPlugin->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)
{
  free(trStrings);
  if((trStrings=MALLOC(const char *,max))) {
    for(int i=0; i<max ; i++) trStrings[i]=tr(strings[i]);
    menu->Add(new cMenuEditStraItem(tr(title),&value,max,trStrings));
    }
}
*/
// --- 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)
{
     /*TODO Add ini file save code to here*/
//  ScPlugin->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]);
  //ScPlugin->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);
    }
}
*/

