#include <vdr/config.h>
#include "autogroup.h"
#include "autogroups.h"
#include "autosort_menu.h"
#include <vdr/plugin.h>


cAutoGroups AutoGroups;

cAutoGroups::cAutoGroups(void)
{
}

cAutoGroups::~cAutoGroups()
{
  cList<cAutoGroup>::Clear(); // valgrind
}


bool cAutoGroups::Load(const char *FileName, bool AllowComments, bool MustExist)
{
  if (cConfig<cAutoGroup>::Load(FileName, AllowComments, MustExist)) {
    // Check for double Group Names
    for (cAutoGroup *group = First(); group; group = Next(group)) {
      for (cAutoGroup *group2 = Next(group); group2; group2 = Next(group2)) {
        if (!strcasecmp(group->Name(),group2->Name())){
	  esyslog("AutoSort -ERROR-  AutoGroup '%s' is double",group->Name());
	  group2->SetName(strcat(group2->Name()," -Double-"));
	  esyslog("AutoSort -ERROR-  second AutoGroup renamed to '%s'",group2->Name());
	  esyslog("       !!! Check your autosort.conf !!!");
	  }
        }
      }
    // Expand Subsection groups
    char *subChar;    
    for (cAutoGroup *group = First(); group; group = Next(group)) {
      if (group->SubSections()) {
        dsyslog("AutoSort-Group '%s': Expanding SubSections", group->Name());
	for (int i = 90; i >= 65; i--) {
          subChar="";	
	  asprintf(&subChar, "%c", i);	
	  cAutoGroup *SubGroup = new cAutoGroup;
	  SubGroup->Copy(group);
	  SubGroup->SetName(strcat(strdup(group->Name())," "));
	  SubGroup->SetName(strcat(SubGroup->Name(),strdup(subChar)));
	  SubGroup->SetPriority(group->Priority() - 1);
	  SubGroup->SetOrder(group->Order() + 1);
	  SubGroup->SetSubSections(false);
	  SubGroup->SetFixedPos( -1 );
	  SubGroup->SetStartName(subChar);
          Add(SubGroup, group);
	  }
        }
      }
    // Add some special groups
    Add(new cAutoGroup);
    cAutoGroup *special = Last();
    special->SetSpecial(); special->SetName("Auto Sort"); special->SetOrder(0);
    if (useFixedAuto) special->SetFixedPos(fixedAuto);
    Add(new cAutoGroup);
    special = Last();
    special->SetSpecial(); special->SetName("Unsorted"); special->SetOrder(1010);
    if (sortUnsorted) special->SetSort(); 
    if (useFixedUnsorted) special->SetFixedPos(fixedUnsorted);
    if (seperateNew){ 
      Add(new cAutoGroup);
      special = Last();
      special->SetSpecial(); special->SetName("New Channels"); special->SetOrder(1020); 
      if (sortNew) special->SetSort();
      if (useFixedNew) special->SetFixedPos(fixedNew);
      }
    ReIndex();
    return true;
    }
//  esyslog("Auto Sort: -ERROR- Can't find %s/autosort.conf -EXITING-",cPlugin::ConfigDirectory());
  esyslog("Auto Sort: -ERROR- Can't find %s/autosort.conf -EXITING-",ConfigDir);
  esyslog("       !!! Check your autosort.conf !!!");
  return false;
}

void cAutoGroups::ReIndex( void )
{
  struct t_map {
    int prio;
    int ord;
    int idx;
    };
  t_map map[Count()];
  t_map dummy;
  bool ready = false;
  for (cAutoGroup *group = First(); group; group = Next(group)) {
    map[group->Index()].idx = group->Index();
    map[group->Index()].prio = group->Priority();
    map[group->Index()].ord = group->Order();
    }
  // Sort by Priority
  while (!ready) { 
    ready = true;    
    for (int n = 0; n < Count(); n++) {
      if ( n + 1 < Count()) {
        if (map[n].prio > map[n+1].prio){
	  ready = false;
	  dummy = map[n+1];
	  map[n+1] = map[n];
	  map[n] = dummy;
	  }
        }
      }
    } // while
    for (int n = 0; n < Count(); n++) {
      cAutoGroup *group = Get(map[n].idx);
      group->SetPIdx(n);
      }            
  ready = false;
  // Sort by Order
  while (!ready) { 
    ready = true;    
    for (int n = 0; n < Count(); n++) {
      if ( n + 1 < Count()) {
        if (map[n].ord > map[n+1].ord){
	  ready = false;
	  dummy = map[n+1];
	  map[n+1] = map[n];
	  map[n] = dummy;
	  }
        }
      }
    } // while
    for (int n = 0; n < Count(); n++) {
      cAutoGroup *group = Get(map[n].idx);
      group->SetOIdx(n);
      }
}

cAutoGroup *cAutoGroups::GetByName (char *search){
  for (cAutoGroup *group = First(); group; group = Next(group)) {
    if (!strcmp(search,group->Name())) return group;
    }
  return NULL;
}

cAutoGroup *cAutoGroups::GetFirstByOrder (void){
  for (cAutoGroup *group = First(); group; group = Next(group)) {
    if (group->OIdx() == 0) return group;
    }
  return NULL;
}

cAutoGroup *cAutoGroups::GetNextByOrder (int OrdIdx){
  OrdIdx++;
  for (cAutoGroup *group = First(); group; group = Next(group)) {
    if (group->OIdx() == OrdIdx ) return group;
    }
  return NULL;
}

cAutoGroup *cAutoGroups::GetFirstByPrio (void){
  for (cAutoGroup *group = First(); group; group = Next(group)) {
    if (group->PIdx() == 0) return group;
    }
  return NULL;
}

cAutoGroup *cAutoGroups::GetNextByPrio (int PrioIdx){
  PrioIdx++;
  for (cAutoGroup *group = First(); group; group = Next(group)) {
    if (group->PIdx() == PrioIdx ) return group;
    }
  return NULL;
}

void cAutoGroups::Dump (void){
  for (cAutoGroup *group = First(); group; group = Next(group)) {
    dsyslog("cAutoGroups::Dump '%s'", group->Name());
    }
}
