#include <CrashTick.h>
#include <ctshared/ctstats.h>

#include <clib/dos_protos.h>
#include <clib/exec_protos.h>

extern ulong DayStatsWritten;

extern struct Config config;

void ProcessWriteStats(void)
{
   struct Area *area;
   struct ConfigNode *cnode;
   struct DiskAreaStats dastat;
   struct DiskNodeStats dnstat;
   struct DateStamp ds;
   BPTR fh;
   ULONG areas,nodes,d,e;

   DateStamp(&ds);

   /* Process new stats */

   if(DayStatsWritten == 0)
      DayStatsWritten = ds.ds_Days;

   for(area=(struct Area *)config.AreaList.First;area;area=area->Next)
   {
      /* Rulla runt */

      if(ds.ds_Days > DayStatsWritten)
      {
         for(d=DayStatsWritten;d<ds.ds_Days;d++)
         {
            for(e=0;e<7;e++)
            {
               area->Last8DaysBytes[7-e]=area->Last8DaysBytes[7-e-1];
               area->Last8DaysFiles[7-e]=area->Last8DaysFiles[7-e-1];
            }

            area->Last8DaysBytes[0]=0;
            area->Last8DaysFiles[0]=0;
         }
      }

      if(area->NewFiles)
      {
         area->Files+=area->NewFiles;
         area->Bytes+=area->NewBytes;

         area->Last8DaysBytes[0]+=area->NewBytes;
         area->Last8DaysFiles[0]+=area->NewFiles;

         if(area->NewFiles)
            area->LastDay=ds.ds_Days;

         if(area->NewFiles && area->FirstTime.ds_Days==0)
            DateStamp(&area->FirstTime);
      }
   }
   
   DayStatsWritten=ds.ds_Days;

   for(cnode=(struct ConfigNode *)config.CNodeList.First;cnode;cnode=cnode->Next)
   {
      if(cnode->FirstDay==0 && (cnode->GotFiles!=0 || cnode->SentFiles!=0))
         cnode->FirstDay=ds.ds_Days;
   }

   if(!(fh=Open(config.cfg_StatsFile,MODE_NEWFILE)))
   {
      LogWrite(1,SYSTEMERR,"Unable to open %s for writing",config.cfg_StatsFile);
      return;
   }

   areas=0;
   nodes=0;

   for(area=(struct Area *)config.AreaList.First;area;area=area->Next)
      areas++;

   for(cnode=(struct ConfigNode *)config.CNodeList.First;cnode;cnode=cnode->Next)
      nodes++;

   /* ID */

   Write(fh,STATS_IDENTIFIER,4);

   /* DayStatsWritten */

   Write(fh,&DayStatsWritten,4);

   /* Number of areas */

   Write(fh,&areas,4);

   /* Areas */

   for(area=(struct Area *)config.AreaList.First;area;area=area->Next)
   {
      strcpy(dastat.Tagname,area->Name);
      dastat.TotalFiles=area->Files;
      dastat.TotalBytes=area->Bytes;
      dastat.LastDay=area->LastDay;
      CopyMem(&area->FirstTime,&dastat.FirstTime,sizeof(struct DateStamp));
      CopyMem(&area->Last8DaysBytes[0],&dastat.Last8DaysBytes[0],8*4);
      CopyMem(&area->Last8DaysFiles[0],&dastat.Last8DaysFiles[0],8*4);
      Copy4D(&dastat.Aka,&area->Aka->Node);
      dastat.Group=area->Group;

      Write(fh,&dastat,sizeof(struct DiskAreaStats));
   }

   /* Number of nodes */

   Write(fh,&nodes,4);

   /* Nodes */

   for(cnode=(struct ConfigNode *)config.CNodeList.First;cnode;cnode=cnode->Next)
   {
      Copy4D(&dnstat.Node,&cnode->Node); 
      dnstat.SentFiles=cnode->SentFiles;
      dnstat.SentBytes=cnode->SentBytes;
      dnstat.GotFiles=cnode->GotFiles;
      dnstat.GotBytes=cnode->GotBytes;
      dnstat.FirstDay=cnode->FirstDay;

      Write(fh,&dnstat,sizeof(struct DiskNodeStats));
   }

   Close(fh);
}

short ReadStats(void)
{
   struct Area *area;
   struct ConfigNode *cnode;
   struct DiskAreaStats dastat;
   struct DiskNodeStats dnstat;
   ULONG c,num;
   BPTR fh;
   UBYTE buf[5];

   DayStatsWritten=0;

   if(!(fh=Open(config.cfg_StatsFile,MODE_OLDFILE)))
      return(TRUE);

   Read(fh,buf,4);
   buf[4]=0;

   if(strcmp(buf,STATS_IDENTIFIER)!=0)
   {
      LogWrite(1,SYSTEMERR,getString(ERR_UNKNOWN_STATS_FORMAT));
      Close(fh);
      return(FALSE);
   }

   /* DayStatsWritten */

   Read(fh,&DayStatsWritten,4);

   /* Number of areas in file */

   Read(fh,&num,4);

   /* Read areas */

   c=0;

   while(c<num && Read(fh,&dastat,sizeof(struct DiskAreaStats))==sizeof(struct DiskAreaStats))
   {
      for(area=(struct Area *)config.AreaList.First;area;area=area->Next)
         if(stricmp(area->Name,dastat.Tagname)==0) break;

      if(area)
      {
         area->Files=dastat.TotalFiles;
         area->Bytes=dastat.TotalBytes;

         CopyMem(&dastat.Last8DaysBytes[0],&area->Last8DaysBytes[0],8*4);
         CopyMem(&dastat.Last8DaysFiles[0],&area->Last8DaysFiles[0],8*4);

         CopyMem(&dastat.FirstTime,&area->FirstTime,sizeof(struct DateStamp));
         area->LastDay=dastat.LastDay;
      }
      c++;
   }

   /* Number of nodes in file */

   Read(fh,&num,4);

   /* Read nodes */

   c=0;

   while(c<num && Read(fh,&dnstat,sizeof(struct DiskNodeStats))==sizeof(struct DiskNodeStats))
   {
      for(cnode=(struct ConfigNode *)config.CNodeList.First;cnode;cnode=cnode->Next)
         if(Compare4D(&dnstat.Node,&cnode->Node)==0) break;

      if(cnode)
      {
         cnode->SentFiles=dnstat.SentFiles;
         cnode->SentBytes=dnstat.SentBytes;
         cnode->GotFiles=dnstat.GotFiles;
         cnode->GotBytes=dnstat.GotBytes;
         cnode->SentFiles=dnstat.SentFiles;
         cnode->FirstDay=dnstat.FirstDay;
      }

      c++;
   }

   Close(fh);
   return(TRUE);
}
