#include "filedoor_structs_defines.h"
#include "filedoor_protos.h"

#include <strings.h>
#include <stdlib.h>
#include <proto/dos.h>
#include <proto/exec.h>
#include <exec/memory.h>

/* Henter samtlige filer i et area ind i hukommelsen */
void FindFiles(struct Areamem *area)
{
BPTR handle;
static char filename[100];
struct File tempfile;
struct Filemem *memfile;

  if(area->files.mlh_Head->mln_Succ!=NULL)
  {
    SortArea(area);
    return;
  }
  area->dirty=FALSE;
  area->filecount=0;
  strcpy(filename,"BBS:cydaldoor/");
  strcat(filename,superarea);
  strcat(filename,"/");
  strcat(filename,area->area.filename);
  if(handle=Open(filename,MODE_OLDFILE))
  {
    while(Read(handle,&tempfile,sizeof(struct File))==sizeof(struct File))
    {
      if(memfile=AllocVec(sizeof(struct Filemem),MEMF_ANY))
      {
        memcpy(&(memfile->f),&tempfile,sizeof(struct File));
        AddTail((struct List *)&(area->files),(struct Node *)memfile);
        area->filecount++;
      }
      else break;
    }
    Close(handle);
  }
  SortArea(area);
}

/* Smid hele lortet ud på disk */
void PurgeAllFiles(void)
{
struct Areamem *area;

  area=firstarea;
  while(area!=NULL)
  {
    PurgeFiles(area);
    area=area->next;
  }
}

/* Find en fil i hukommelsen ud fra filnavnet */
struct Filemem *FindFileInArea(char *filename,struct Areamem *area)
{
struct Filemem *file;

  if(area->files.mlh_Head->mln_Succ==NULL) FindFiles(area);
  file=(struct Filemem *)area->files.mlh_Head;
  while(file->n.mln_Succ!=NULL)
  {
    if(stricmp(filename,file->f.name)==0) return(file);
    file=(struct Filemem *)file->n.mln_Succ;
  }
  return(NULL);
}

/* Skriver alle filer i et område tilbage til disk og deallokerer den benyttede hukommelse */
void PurgeFiles(struct Areamem *area)
{
struct MinNode *node;
BPTR handle;
static char filename[100];

  strcpy(filename,"BBS:cydaldoor/");
  strcat(filename,superarea);
  strcat(filename,"/");
  strcat(filename,area->area.filename);
  if(area->dirty)
  { /* Write back & deallocate */
    if(area->files.mlh_Head->mln_Succ!=NULL)
    {
      if(handle=Open(filename,MODE_NEWFILE))
      {
        while(node=(struct MinNode *)RemHead((struct List *)&(area->files)))
        {
          Write(handle,&(((struct Filemem *)node)->f),sizeof(struct File));
          FreeVec(node);
        }
        Close(handle);
      }
    }
  }
  else /* Simply deallocate to purge */
    while(node=(struct MinNode *)RemHead((struct List *)&(area->files)))
      FreeVec(node);
}

/* Lokaliserer og initialiserer alle områder i cydal-skuffen */
void FindAreas(void)
{
BPTR sahandle;
struct Areamem *prevarea,*newarea;
struct Area temparea;
static char filename[100];

  /* Find alle areas i dette superarea */
  numareas=0;
  prevarea=firstarea=NULL;
  strcpy(filename,"BBS:cydaldoor/");
  strcat(filename,superarea);
  strcat(filename,".superarea");
  if(sahandle=Open(filename,MODE_OLDFILE))
  {
    while(sizeof(struct Area)==Read(sahandle,&temparea,sizeof(struct Area)))
    {
      if(accesslevel<temparea.access) continue;
      if(newarea=AllocVec(sizeof(struct Areamem),MEMF_ANY))
      {
        memcpy(&(newarea->area),&temparea,sizeof(struct Area));
        numareas++;
        NewList((struct List *)&newarea->files);
        if(firstarea==NULL) firstarea=newarea; else prevarea->next=newarea;
        prevarea=newarea;
      }
      else break;
    }
    Close(sahandle);
    if(prevarea!=NULL) prevarea->next=NULL;
  }
}

/* Zapper alle areas ud af hukommelsen */
/* Zapper osse alle filer og taggede filer */
void FreeAreas(void)
{
struct Areamem *currentarea,*temp;

  msg("\xc"); /* Bare så brugeren ved maskinen lever endnu */
  currentarea=firstarea;
  while(currentarea!=NULL)
  {
    /* Slip af med filer der evt. er hentet ind i areaet */
    PurgeFiles(currentarea);
    /* Slip af med områdets hukommelse */
    temp=currentarea;
    currentarea=currentarea->next;
    FreeVec(temp);
  }
}


/* Spol et antal nodes frem i en hægtet liste af filer */
struct Filemem *MoveForward(struct Filemem *f,int i)
{
  while(f->n.mln_Succ!=NULL && i)
  {
    i--;
    f=(struct Filemem *)f->n.mln_Succ;
  }
  return(f);
}

/* Spol et antal nodes tilbage i en hægtet liste af filer */
struct Filemem *MoveBack(struct Filemem *f,int i)
{
  while(f->n.mln_Pred!=NULL && i)
  {
    i--;
    f=(struct Filemem *)f->n.mln_Pred;
  }
  return(f);
}

/* Find forrige area i listen - suk. så skulle det bruges alligevel */
struct Areamem *PrevArea(struct Areamem *area)
{
struct Areamem *temparea;

  if(firstarea==area) return(NULL);
  temparea=firstarea;
  while(temparea->next!=area)
  {
    if(!(temparea=temparea->next)) return(NULL);
  }
  return(temparea);
}

int comparefilesa(struct Filemem **a,struct Filemem **b)
{
  return(stricmp((*a)->f.name,(*b)->f.name));
}

int comparefilesz(struct Filemem **a,struct Filemem **b)
{
  return(stricmp((*b)->f.name,(*a)->f.name));
}

int comparefilesn(struct Filemem **a,struct Filemem **b)
{
  if((*a)->f.date > (*b)->f.date) return(-1);
  if((*a)->f.date < (*b)->f.date) return(1);
  return(0);
}

int comparefileso(struct Filemem **a,struct Filemem **b)
{
  if((*a)->f.date < (*b)->f.date) return(-1);
  if((*a)->f.date > (*b)->f.date) return(1);
  return(0);
}


/* Sorter filerne i et area */
void SortArea(struct Areamem *area)
{
struct Filemem **fileslist;
struct Filemem *file;
int i=0;
char *sortmethod;

  if(fileslist=AllocVec(area->filecount*sizeof(void *),MEMF_ANY))
  {
    file=(struct Filemem *)area->files.mlh_Head;
    while(file->n.mln_Succ!=NULL)
    {
      fileslist[i++]=file;
      file=(struct Filemem *)file->n.mln_Succ;
    }
    sortmethod=FindAttr('S');
    if(sortmethod==NULL) sortmethod="A";
    switch(sortmethod[0])
    {
      case 'A':
      qsort(fileslist,area->filecount,sizeof(struct Filemem *),comparefilesa);
      break;

      case 'Z':
      qsort(fileslist,area->filecount,sizeof(struct Filemem *),comparefilesz);
      break;

      case 'N':
      qsort(fileslist,area->filecount,sizeof(struct Filemem *),comparefilesn);
      break;

      case 'O':
      qsort(fileslist,area->filecount,sizeof(struct Filemem *),comparefileso);
      break;
    }
    NewList((struct List *)&area->files);
    for(i=0;i<area->filecount;i++)
    {
      AddTail((struct List *)&area->files,(struct Node *)fileslist[i]);
    }
    FreeVec(fileslist);
  }
}
