#include <vdr/tools.h>
#include "autosort_main.h"
#include <vdr/channels.h>

/*
class cAutoGroup : public cListObject {
private:
  char *name;
  int priority;
  int pIdx;
  int order;
  int oIdx;
  int fixedPos;  
  char *startName;
  struct t_hasName{
    char *hasName;
    };
  t_hasName hasNameList[MAXAUTOOPTIONS];
  struct t_notName{
    char *notName;
    };
  t_notName notNameList[MAXAUTOOPTIONS];
  struct t_hasSource{
    char *hasSource;
    };
  t_hasSource hasSourceList[MAXAUTOOPTIONS];
  struct t_hasProvider{
    char *hasProvider;
    };
  t_hasProvider hasProviderList[MAXAUTOOPTIONS];    
  struct t_notProvider{
    char *notProvider;
    };
  t_notProvider notProviderList[MAXAUTOOPTIONS];    
  struct t_caValue{
    char *caValue;
    };
  t_caValue caValueList[MAXAUTOOPTIONS];    
  struct t_notCaValue{
    char *notCaValue;
    };
  t_notCaValue notCaValueList[MAXAUTOOPTIONS];    
  struct t_audioLang{
    char *audioLang;
    };
  t_audioLang audioLangList[MAXAUTOOPTIONS];    
  bool subSections;
  bool sort;
  bool keepHere;
  bool setCaFF;
  bool setCa0;
  bool isSpecial;
  // Tri-states
  // -1 : must NOT have
  //  0 : don't care
  //  1 : must have
  int hasApid;
  int hasVpid;
  int hasTpid;
  int hasCa;
  int hasOpenCa;
  int hasClosedCa;
  int timeStampDays;
public:
  cAutoGroup(void);
  virtual ~cAutoGroup();
  cAutoGroup *Copy(cAutoGroup *OldGroup);
  bool Parse(const char *s);
  void Print(void);
  char *Name(void)                       { return name; };
  void SetName(char *Name)               { name = strdup(Name); };
  char *StartName(void)                  { return startName; };
  void SetStartName(char *StartName)     { startName = strdup(StartName); };
  int Priority (void)                    { return priority; };  
  void SetPriority (int Priority)        { priority = Priority; }; 
  int Order (void)                       { return order; };  
  int OIdx (void)                        { return oIdx; };  
  int PIdx (void)                        { return pIdx; };  
  bool KeepHere (void)                   { return keepHere; };
  bool Sort (void)                       { return sort; };
  bool SubSections (void)                { return subSections; };
  void SetSubSections (bool SubSections) { subSections = SubSections; };
  bool IsSpecial (void)                  { return isSpecial; };
  bool SetCaFF (void)                    { return setCaFF; };
  bool SetCa0 (void)                     { return setCa0; };
  void SetOrder (int Order)              { order = Order; };
  void SetFixedPos (int FPos)            { fixedPos = FPos; };
  int FixedPos (void)                    { return fixedPos; };
  void SetPIdx (int PIdx)                { pIdx = PIdx; }; 
  void SetOIdx (int OIdx)                { oIdx = OIdx; }; 
  void SetSort (void)                    { sort = true; }; 
  void SetSpecial (void)                 { isSpecial = true; };
  int HasApid (void)                     { return hasApid; };
  int HasVpid (void)                     { return hasVpid; };
  int HasTpid (void)                     { return hasTpid; };
  int HasCa (void)                       { return hasCa; };
  int HasOpenCa (void)                   { return hasOpenCa; };
  int HasClosedCa (void)                 { return hasClosedCa; };
  int TimeStampDays (void)               { return timeStampDays; };
  char *HasName (int NIdx)               { return hasNameList[NIdx].hasName; };
  char *NotName (int nNIdx)              { return notNameList[nNIdx].notName; };
  char *HasSource (int SIdx)             { return hasSourceList[SIdx].hasSource; };
  char *HasProvider (int PrIdx)          { return hasProviderList[PrIdx].hasProvider; };
  char *NotProvider (int PrIdx)          { return notProviderList[PrIdx].notProvider; };
  char *CaValue (int CaIdx)              { return caValueList[CaIdx].caValue; };
  char *NotCaValue (int nCaIdx)          { return notCaValueList[nCaIdx].notCaValue; };
  char *AudioLang (int AIdx)             { return audioLangList[AIdx].audioLang; };
  int GetChIndex(void);
  };
*/


cAutoGroup::cAutoGroup(void)
{
  pIdx = 0;
  oIdx = 0;
  name = strdup("");
  startName = strdup("");
  hasNameList[0].hasName         = strdup("NotSet");
  notNameList[0].notName         = strdup("NotSet");
  hasSourceList[0].hasSource     = strdup("NotSet");
  hasProviderList[0].hasProvider = strdup("NotSet");
  notProviderList[0].notProvider = strdup("NotSet");
  caValueList[0].caValue         = strdup("NotSet");
  notCaValueList[0].notCaValue   = strdup("NotSet");
  audioLangList[0].audioLang     = strdup("NotSet");
  priority = 99;
  order = 500;
  fixedPos = -1;
  subSections = false;
  sort = false;
  keepHere = false;
  setCaFF = false;
  setCa0 = false;
  isSpecial = false;
  hasApid = 0;
  hasVpid = 0;
  hasTpid = 0;
  hasCa = 0;
  hasOpenCa = 0;
  hasClosedCa = 0;
  timeStampDays = 0;
}

cAutoGroup *cAutoGroup::Copy(cAutoGroup *OldGroup)
{
  cAutoGroup *NewGroup = new cAutoGroup;
  int i;
  name        = OldGroup->Name();
  priority    = OldGroup->Priority();
  order       = OldGroup->Order();
  fixedPos    = OldGroup->FixedPos();
  subSections = OldGroup->SubSections();
  sort        = OldGroup->Sort();
  keepHere    = OldGroup->KeepHere();
  setCaFF     = OldGroup->SetCaFF();
  setCa0      = OldGroup->SetCa0();
  isSpecial   = OldGroup->IsSpecial();
  hasApid     = OldGroup->HasApid();
  hasVpid     = OldGroup->HasVpid();
  hasTpid     = OldGroup->HasTpid();
  hasCa       = OldGroup->HasCa();
  hasOpenCa   = OldGroup->HasOpenCa();
  hasClosedCa = OldGroup->HasClosedCa();
  timeStampDays = OldGroup->TimeStampDays();
  i = 0; while (strcmp(OldGroup->HasName(i),     "NotSet") != 0) { hasNameList[i].hasName         = OldGroup->HasName(i);     i++; } hasNameList[i].hasName         = strdup("NotSet");
  i = 0; while (strcmp(OldGroup->NotName(i),     "NotSet") != 0) { notNameList[i].notName         = OldGroup->NotName(i);     i++; } notNameList[i].notName         = strdup("NotSet");
  i = 0; while (strcmp(OldGroup->HasSource(i),   "NotSet") != 0) { hasSourceList[i].hasSource     = OldGroup->HasSource(i);   i++; } hasSourceList[i].hasSource     = strdup("NotSet");
  i = 0; while (strcmp(OldGroup->HasProvider(i), "NotSet") != 0) { hasProviderList[i].hasProvider = OldGroup->HasProvider(i); i++; } hasProviderList[i].hasProvider = strdup("NotSet");
  i = 0; while (strcmp(OldGroup->NotProvider(i), "NotSet") != 0) { notProviderList[i].notProvider = OldGroup->NotProvider(i); i++; } notProviderList[i].notProvider = strdup("NotSet");
  i = 0; while (strcmp(OldGroup->CaValue(i),     "NotSet") != 0) { caValueList[i].caValue         = OldGroup->CaValue(i);     i++; } caValueList[i].caValue         = strdup("NotSet");
  i = 0; while (strcmp(OldGroup->NotCaValue(i),  "NotSet") != 0) { notCaValueList[i].notCaValue   = OldGroup->NotCaValue(i);  i++; } notCaValueList[i].notCaValue   = strdup("NotSet");
  i = 0; while (strcmp(OldGroup->AudioLang(i),   "NotSet") != 0) { audioLangList[i].audioLang     = OldGroup->AudioLang(i);   i++; } audioLangList[i].audioLang     = strdup("NotSet");
  return NewGroup;
}

cAutoGroup::~cAutoGroup()
{
}

int cAutoGroup::GetChIndex(void)
{
  cChannel *channel = Channels.Last();
  while (channel){
    if ((strcmp(channel->Name(),name) == 0) && channel->GroupSep()) return channel->Index();
    if (strcmp(channel->Name(),"Auto Sort") == 0) return 0;
    channel = Channels.Get(Channels.GetPrevGroup(channel->Index()));
    }  
  return 0;
}

void cAutoGroup::Print(void)
{
  int i = 0;
  dsyslog("AutoGroupPrint:");
  dsyslog("  Name:          %s",name);
  dsyslog("  Index:         %d",Index());
  dsyslog("  Priority:      %d",priority);
  dsyslog("  Priority Index:%d",pIdx);
  dsyslog("  Order:         %d",order);
  dsyslog("  Order Index:   %d",oIdx);
  if (fixedPos < 0) { 		dsyslog("  FixedPosition: None");}
    else {            		dsyslog("  FixedPosition: %d",fixedPos); }
  if (timeStampDays == 0) { 	dsyslog("  TimeStamp:     Dont't care about");}
    else {            		dsyslog("  TimeStamp:     %d days old",timeStampDays); }
  if (subSections) {  		dsyslog("  SubSections:   Yes"); }
    else {            		dsyslog("  SubSections:   No"); }
  if (sort) {         		dsyslog("  Sort:          Yes"); }
    else {            		dsyslog("  Sort:          No"); }
  if (keepHere) {     		dsyslog("  KeepHere:      Yes"); }
    else {            		dsyslog("  KeepHere:      No"); }
  if (setCaFF) {      		dsyslog("  SetCaFF:       Yes"); }
    else {            		dsyslog("  SetCaFF:       No"); }
  if (setCa0) {       		dsyslog("  SetCa0:        Yes"); }
    else {            		dsyslog("  SetCa0:        No"); }
  if (hasApid  < 0) {     	dsyslog("  Apid:          Must NOT have"); }
  if (hasApid == 0) {     	dsyslog("  Apid:          Don't care about"); }
  if (hasApid  > 0) {     	dsyslog("  Apid:          Must have"); }
  if (hasVpid  < 0) {     	dsyslog("  Vpid:          Must NOT have"); }
  if (hasVpid == 0) {     	dsyslog("  Vpid:          Don't care about"); }
  if (hasVpid  > 0) {     	dsyslog("  Vpid:          Must have"); }
  if (hasTpid  < 0) {     	dsyslog("  Tpid:          Must NOT have"); }
  if (hasTpid == 0) {     	dsyslog("  Tpid:          Don't care about"); }
  if (hasTpid  > 0) {     	dsyslog("  Tpid:          Must have"); }
  if (hasCa  < 0) {       	dsyslog("  Ca:            Must NOT have"); }
  if (hasCa == 0) {       	dsyslog("  Ca:            Don't care about"); }
  if (hasCa  > 0) {       	dsyslog("  Ca:            Must have"); }
  if (hasOpenCa  < 0) {   	dsyslog("  OpenCa:        Must NOT have"); }
  if (hasOpenCa == 0) {   	dsyslog("  OpenCa:        Don't care about"); }
  if (hasOpenCa  > 0) {   	dsyslog("  OpenCa:        Must have"); }  
  if (hasClosedCa  < 0) { 	dsyslog("  ClosedCa:      Must NOT have"); }
  if (hasClosedCa == 0) { 	dsyslog("  ClosedCa:      Don't care about"); }
  if (hasClosedCa  > 0) { 	dsyslog("  ClosedCa:      Must have"); }
  if (!strcmp(startName,"")) { 	dsyslog("  StartName:     Don't care about");}
    else {                     	dsyslog("  StartName:     %s",startName); }
  i = 0; while (strcmp(hasNameList[i].hasName,"NotSet") != 0) {
                          dsyslog("  HasName[%d]     %s",i ,hasNameList[i].hasName); i++; }
  i = 0; while (strcmp(notNameList[i].notName,"NotSet") != 0) {
                          dsyslog("  NotName[%d]     %s",i ,notNameList[i].notName); i++; }
  i = 0; while (strcmp(hasSourceList[i].hasSource,"NotSet") != 0) {
                          dsyslog("  HasSource[%d]   %s",i ,hasSourceList[i].hasSource); i++; }
  i = 0; while (strcmp(hasProviderList[i].hasProvider,"NotSet") != 0) {
                          dsyslog("  HasProvider[%d] %s",i ,hasProviderList[i].hasProvider); i++; }
  i = 0; while (strcmp(notProviderList[i].notProvider,"NotSet") != 0) {
                          dsyslog("  NotProvider[%d] %s",i ,notProviderList[i].notProvider); i++; }
  i = 0; while (strcmp(caValueList[i].caValue,"NotSet") != 0) {
                          dsyslog("  CaValue[%d]     %s",i ,caValueList[i].caValue); i++; }
  i = 0; while (strcmp(notCaValueList[i].notCaValue,"NotSet") != 0) {
                          dsyslog("  NotCaValue[%d]  %s",i ,notCaValueList[i].notCaValue); i++; }
  i = 0; while (strcmp(audioLangList[i].audioLang,"NotSet") != 0) {
                          dsyslog("  AudioLang[%d]   %s",i ,audioLangList[i].audioLang); i++; }
}

bool cAutoGroup::Parse(const char *line)
{
/*  char *subline;
  subline = strdup(line);
  char *option = strtok(subline,":");
  name = strdup(option);

  char *buf;
  //bool nameFound = false;
  int i = 0;

  asprintf(&buf, "%s/%s/%s",cPlugin::ConfigDirectory(),"autosort",name );
    if (access(buf, R_OK) == 0) {
      dsyslog ("There is a file i should read: %s", buf);
      FILE *f = fopen(buf, "r");
      if (f) {
        char buffer[MAXPARSEBUFFER];
        while (fgets(buffer, sizeof(buffer), f) > 0) {
          if (!isempty(buffer)) {
            dsyslog("read: %s",buffer);
            }
          }
        fclose(f);
        }
      }

  option = strtok(NULL,":");
  while (option != NULL)
  {
    //if      (!nameFound) { 
      //name = option; nameFound = true; 
      //}
         if (!strcasecmp(option, "HasApid"))          hasApid =  1;
*/

  char *subline;
  subline = strdup(line);
  char *option = strtok(subline,":");
  bool nameFound = false;
  int i = 0;
  while (option != NULL)
  {
    if      (!nameFound) { name = option; nameFound = true; }
    else if (!strcasecmp(option, "HasApid"))          hasApid =  1; 
    else if (!strcasecmp(option, "HasNoApid"))        hasApid = -1; 
    else if (!strcasecmp(option, "HasVpid"))          hasVpid =  1; 
    else if (!strcasecmp(option, "HasNoVpid"))        hasVpid = -1; 
    else if (!strcasecmp(option, "HasTpid"))          hasTpid =  1; 
    else if (!strcasecmp(option, "HasNoTpid"))        hasTpid = -1; 
    else if (!strcasecmp(option, "HasCa"))            hasCa =  1; 
    else if (!strcasecmp(option, "HasNoCa"))          hasCa = -1; 
    else if (!strcasecmp(option, "HasOpenCa"))        hasOpenCa =  1; 
    else if (!strcasecmp(option, "HasNoOpenCa"))      hasOpenCa = -1; 
    else if (!strcasecmp(option, "HasClosedCa"))      hasClosedCa =  1; 
    else if (!strcasecmp(option, "HasNoClosedCa"))    hasClosedCa = -1; 
    else if (!strcasecmp(option, "SubSections"))      subSections = true; 
    else if (!strcasecmp(option, "Sort"))             sort = true; 
    else if (!strcasecmp(option, "keepHere"))         keepHere = true; 
    else if (!strcasecmp(option, "SetCaFF"))          setCaFF = true; 
    else if (!strcasecmp(option, "SetCa0"))           setCa0 = true; 
    else if (!strncasecmp(option, "Priority",8))    { strsep(&option,"="); priority = atoi(option); } 
    else if (!strncasecmp(option, "Order",5))       { strsep(&option,"="); order =    atoi(option); } 
    else if (!strncasecmp(option, "FixedPos",8))    { strsep(&option,"="); fixedPos = atoi(option); } 
    else if (!strncasecmp(option, "TimeStamp",9))   { strsep(&option,"="); timeStampDays = atoi(option); } 
    else if (!strncasecmp(option, "StartName",9))   { strsep(&option,"="); startName = option; } 
    else if (!strncasecmp(option, "HasName",7))     { strsep(&option,"="); i = 0;
                                                      while (strcmp(hasNameList[i].hasName,"NotSet")) { i++; }
                                                      hasNameList[i  ].hasName = strdup(UpString(option));
                                                      hasNameList[i+1].hasName = strdup("NotSet"); }
    else if (!strncasecmp(option, "NotName",7))     { strsep(&option,"="); i = 0;
                                                      while (strcmp(notNameList[i].notName,"NotSet")) { i++; }
                                                      notNameList[i  ].notName = strdup(UpString(option));
                                                      notNameList[i+1].notName = strdup("NotSet"); }
    else if (!strncasecmp(option, "HasSource",9))   { strsep(&option,"="); i = 0;
                                                      while (strcmp(hasSourceList[i].hasSource,"NotSet")) { i++; }
                                                      hasSourceList[i  ].hasSource = strdup(UpString(option));
                                                      hasSourceList[i+1].hasSource = strdup("NotSet"); }
    else if (!strncasecmp(option, "HasProvider",11)) { strsep(&option,"="); i = 0;
                                                      while (strcmp(hasProviderList[i].hasProvider,"NotSet")) { i++; }
                                                      hasProviderList[i  ].hasProvider = strdup(UpString(option));
                                                      hasProviderList[i+1].hasProvider = strdup("NotSet"); }
    else if (!strncasecmp(option, "NotProvider",11)) { strsep(&option,"="); i = 0;
                                                      while (strcmp(notProviderList[i].notProvider,"NotSet")) { i++; }
                                                      notProviderList[i  ].notProvider = strdup(UpString(option));
                                                      notProviderList[i+1].notProvider = strdup("NotSet"); }
    else if (!strncasecmp(option, "CaValue",7))     { strsep(&option,"="); i = 0;
                                                      while (strcmp(caValueList[i].caValue,"NotSet")) { i++; }
                                                      caValueList[i  ].caValue = strdup(UpString(option));
                                                      caValueList[i+1].caValue = strdup("NotSet"); }
    else if (!strncasecmp(option, "NotCaValue",10)) { strsep(&option,"="); i = 0;
                                                      while (strcmp(notCaValueList[i].notCaValue,"NotSet")) { i++; }
                                                      notCaValueList[i  ].notCaValue = strdup(UpString(option));
                                                      notCaValueList[i+1].notCaValue = strdup("NotSet"); }
    else if (!strncasecmp(option, "AudioLang",9))   { strsep(&option,"="); i = 0;
                                                      while (strcmp(audioLangList[i].audioLang,"NotSet")) { i++; }
                                                      audioLangList[i  ].audioLang = strdup(UpString(option));
                                                      audioLangList[i+1].audioLang = strdup("NotSet"); }
    option = strtok(NULL,":");
  }
  //Print();
  if (!strcasecmp(name,"Auto Sort") ||
      !strcasecmp(name,"Unsorted") ||
      !strcasecmp(name,"Dummy") ||
      !strcasecmp(name,"Dummy2") ||
      !strcasecmp(name,"New Channels")) {
	esyslog("AutoSort -ERROR-  Found unallowed AutoGroup name: '%s'",name);
	esyslog("       !!! Check your autosort.conf !!!");
        return false;
	}
  else if (priority < 0 || priority > 99  ||
           order    < 1 || order    > 999 ||
           fixedPos < -1 ) {
	     esyslog("AutoSort -ERROR-  Found wrong Priority, Order or FixedPos in AutoGroup '%s'",name);
	     esyslog("       !!! Check your autosort.conf !!!");
             return false;     
             }
  else if (setCaFF && setCa0) {
	esyslog("AutoSort -ERROR-  Found SetCaFF and SetCa0 in same AutoGroup '%s'",name);
	esyslog("       !!! Check your autosort.conf !!!");
        return false;
	}  
  else return true;
}

