/*
 * entry.c: Data structure to handle still pictures
 *
 * See the README file for copyright information and how to reach the author.
 *
 * $Id: entry.c 2.1 2012/02/17 14:00:28 kls Exp $
 */

#include "entry.h"

cPictureEntry::cPictureEntry(const char *Name, const cPictureEntry *Parent, bool IsDirectory)
{
  name = strdup(Name);
  parent = Parent;
  isDirectory = IsDirectory;
  entries = NULL;
}

cPictureEntry::~cPictureEntry()
{
  free(name);
  delete entries;
}

int cPictureEntry::Compare(const cListObject &ListObject) const
{
  cPictureEntry *p = (cPictureEntry *)&ListObject;
  if (IsDirectory() && !p->IsDirectory())
     return -1;
  if (!IsDirectory() && p->IsDirectory())
     return +1;
  if (IsDirectory())
     return strcoll(name, p->name);
  else
     return strcmp(name, p->name); // correctly sorts dsc01234.jpg and dsc01234a.jpg in case pictures have been "squeezed in"
}

cString cPictureEntry::Path(void) const
{
  return parent ? *AddDirectory(parent->Path(), name) : name;
}

void cPictureEntry::Load(void) const
{
  if (isDirectory && !entries) {
     cString Directory = Path();
     cReadDir d(Directory);
     if (d.Ok()) {
        struct dirent *e;
        while ((e = d.Next()) != NULL) {
              struct stat ds;
              if (stat(AddDirectory(Directory, e->d_name), &ds) == 0) {
                 if (!entries)
                    entries = new cList<cPictureEntry>;
                 entries->Add(new cPictureEntry(e->d_name, this, S_ISDIR(ds.st_mode)));
                 }
              }
        if (entries)
           entries->Sort();
        }
     else
        LOG_ERROR_STR(*Directory);
     }
}

const cList<cPictureEntry> *cPictureEntry::Entries(void) const
{
  Load();
  return entries;
}

const cPictureEntry *cPictureEntry::FirstPicture(void) const
{
  Load();
  if (entries) {
     for (cPictureEntry *pe = entries->First(); pe; pe = entries->Next(pe)) {
         if (pe->IsDirectory()) {
            const cPictureEntry *p = pe->FirstPicture();
            if (p)
               return p;
            }
         else
            return pe;
         }
     }
  return NULL;
}

const cPictureEntry *cPictureEntry::LastPicture(void) const
{
  Load();
  if (entries) {
     for (cPictureEntry *pe = entries->Last(); pe; pe = entries->Prev(pe)) {
         if (pe->IsDirectory()) {
            const cPictureEntry *p = pe->LastPicture();
            if (p)
               return p;
            }
         else
            return pe;
         }
     }
  return NULL;
}

const cPictureEntry *cPictureEntry::PrevPicture(const cPictureEntry *This) const
{
  if (This) {
     const cPictureEntry *pe = (cPictureEntry *)entries->Prev(This);
     if (pe) {
        if (pe->IsDirectory()) {
           const cPictureEntry *p = pe->LastPicture();
           if (p)
              return p;
           return PrevPicture(pe);
           }
        return pe;
        }
     }
  if (parent)
     return parent->PrevPicture(this);
  return NULL;
}

const cPictureEntry *cPictureEntry::NextPicture(const cPictureEntry *This) const
{
  if (This) {
     cPictureEntry *pe = (cPictureEntry *)entries->Next(This);
     if (pe) {
        if (pe->IsDirectory()) {
           const cPictureEntry *p = pe->FirstPicture();
           if (p)
              return p;
           return NextPicture(pe);
           }
        return pe;
        }
     }
  else if (IsDirectory()) {
     const cPictureEntry *p = FirstPicture();
     if (p)
        return p;
     }
  if (parent)
     return parent->NextPicture(this);
  return NULL;
}