/*->c.band */

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <signal.h>
#include <ctype.h>
#include <time.h>

#include "h.os"
#include "h.wimp"
#include "h.bbc"
#include "h.flex"

#include "h.Drawlevel0"


#include "h.def"
#include "h.wos"
#include "h.main"
#include "h.strdef"
#include "h.mym"
#include "h.serial"
#include "h.ram"
#include "h.file"
#include "h.pr"
#include "h.key"
#include "h.script"
#include "h.timex"
#include "h.fsx"
#include "h.dir"
#include "h.view"
#include "h.txfax"
#include "h.config"
#include "h.batch"
#include "h.trans"
#include "h.state"
#include "h.xext"

#include "h.etc"

#include "h.band"






typedef struct splitstr
{
 int  start;
 int  cost;
 char priority;
 char last;
 int  qcost;
 int  qtime;
 int  mincost;

} splitstr;


typedef struct bandstr
{
 char name[8];

 int  day[7];    /* index into array of splitstr's */

} bandstr;


static bandstr  * band;
static splitstr * split;

       int        bands;
static int        splits;



#define BCHUNK 0x200
#define SCHUNK 0x200



void bandinit(void)
{
 flex_alloc((flex_ptr)&band,BCHUNK);
 flex_alloc((flex_ptr)&split,SCHUNK);
 bands=splits=0;
}



char * bandname(int bn)
{
 if(bn>=0 && bn<bands) return(band[bn].name);
 return("None");
}



int bandnametoband(char * name)
{
 int bn;

 for(bn=0;bn<bands;bn++)
 {
  if(!cstrcmp(band[bn].name,name)) return(bn);
 }

 return(-1);
}




/* 
   define a band 
   setband(string & name,string & days,string & data);

   data is start time,cost per second * 100000,priority,qtime,qcost,min cost

   setband("b1","SuMoTuWeThFrSa"," 0,10,3,
                                   8,20,0,
                                  13,10,2,
                                  18,10,4",0);
 */



#define MAXD 7 


static char * days[MAXD]=
{
 "Mo",
 "Tu",
 "We",
 "Th",
 "Fr",
 "Sa",
 "Su",
};


void setband(int fp)
{
 char * p;
 int    bn;
 char   temp[1024];
 char   d[4];
 int    splitstart;
 int    time;
 int    cost;
 int    priority;
 int    qtime;
 int    qcost;
 int    mincost;
 int    i;
 int    colon;
 int    ch;

 strcpy(temp,stringptr(stack[fp]));

 for(bn=0;bn<bands;bn++)
  if(!cstrcmp(band[bn].name,temp)) break;

 if(bn>=bands)
 {
  /* add a band */

  flex_chunk((flex_ptr)&band,(bands+1)*sizeof(bandstr),BCHUNK);
  bands++;
  strcpy(band[bn].name,temp);

  for(i=0;i<MAXD;i++) band[bn].day[i]=-1;
 }

 strcpy(temp,stringptr(stack[fp+2]));
 p=temp;

 splitstart=splits;

 while(*p)
 {               /* get three numbers, add a split */
  colon=0;
  time=0;
  while((ch=*p++)!=0)
  {
   if(ch==',') break;
   else
   if(ch==':') {time*=60;colon=0;}
   else         time=time*10+(ch-'0');
  }
  if(!colon && time<=24) time*=60;
  time*=60;
  if(!ch || ch!=',') break;


  cost=0;
  while((ch=*p++)!=0)
  {
   if(ch==',') break;
   else 
   if(isdigit(ch)) cost=cost*10+(ch-'0');
  }
  if(!ch || ch!=',') break;


  priority=0;
  while((ch=*p++)!=0)
  {
   if(ch==',') break;
   else
   if(isdigit(ch)) priority=priority*10+(ch-'0');
  }
  if(!ch || ch!=',') break;


  qtime=0;
  while((ch=*p++)!=0)
  {
   if(ch==',') break;
   else
   if(isdigit(ch)) qtime=qtime*10+(ch-'0');
  }
  if(!ch || ch!=',') break;


  qcost=0;
  while((ch=*p++)!=0)
  {
   if(ch==',') break;
   else
   if(isdigit(ch)) qcost=qcost*10+(ch-'0');
  }
  if(!ch || ch!=',') break;

  mincost=0;
  while((ch=*p++)!=0)
  {
   if(ch==',' || ch==';') break;
   else
   if(isdigit(ch)) mincost=mincost*10+(ch-'0');
  }

  if(ch && !(ch==',' || ch==';')) break;


  flex_chunk((flex_ptr)&split,(splits+1)*sizeof(splitstr),SCHUNK);

  split[splits].start=time;
  split[splits].cost=cost;
  split[splits].priority=priority;
  split[splits].qcost=qcost;
  split[splits].qtime=qtime;
  split[splits].mincost=mincost;
  split[splits].last=0;

  splits++;
 }

 if(splits) split[splits-1].last=1;


 strcpy(temp,stringptr(stack[fp+1]));
 p=temp;
           /* now sort out the days of the week */
 while(*p)
 {
  d[0]=*p++;
  d[1]=*p++;
  d[2]=0;
  if(*p==',') p++;

  for(i=0;i<MAXD;i++)
   if(!cstrcmp(days[i],d))
   {
    band[bn].day[i]=splitstart;
   }
 }

}


/* input a band number, a priority, current time in seconds through day */
/* and the day of the week                                              */
/* return after time, maybe less than current                           */
/* if clock wraps, the time we return can be greater than 24 hours      */

int getbandaftertime(int bn,int priority,int current,int day) 
{
 int sn;
 int st;
 int shift;
 int timeday;
 int d;

 shift=0;

/* dprintf(0,"bn=%d p=%d c=%d d=%d",bn,priority,current,day);*/


 if(bn>=0 && bn<bands)
 {
  sn=st=band[bn].day[day];
  if(sn>-1)
  {
   while(split[sn].start<current && !split[sn].last) sn++;
   if(split[sn].start>current && sn>st) sn--;

  /* dprintf(0,"sn1=%d",sn); */

   if(split[sn].start<=current)
   {
    timeday=current;

    for(d=0;d<7;d++)
    {
     if(d!=0) 
     {
      sn=band[bn].day[(day+d) % 0x7];
      if(sn<0) break;
      timeday=0;
     }

     while(1)
     {
      /* dprintf(0,"sn2=%d last=%d",sn,split[sn].last); */

      if(priority<=split[sn].priority) 
      {
       d=7;       /* break outer loop */
       break;
      }

      if(split[sn].last)
      {
       shift+=(24*60*60)-timeday;
       break;
      }
      else
      {
       shift+=split[sn+1].start-timeday;
       timeday=split[sn+1].start;
      }
      sn++;
     }
    }
   }
  }
 }
 return(current+shift);
}




/* return cost of call in pence given band, time of day, day and duration */

int getcost(int bn,int current,int day,int duration)
{
 int sn;
 int st;
 int cost;
 int qcost;
 int qtime;
 int mincost;

 cost=0;

 if(bn>=0 && bn<bands)
 {
  sn=st=band[bn].day[day];
  if(sn>-1)
  {
   while(split[sn].start<current && !split[sn].last) sn++;
   if(split[sn].start>current && sn>st) sn--;

   if(split[sn].start<current)
   {
    qcost=split[sn].qcost;
    qtime=split[sn].qtime;
    mincost=split[sn].mincost;

 /* dprintf(3,"qcost=%d qtime=%d mincost=%d cost=%d",qcost,qtime,
                                             mincost,split[sn].cost); */

    duration=((duration+qtime)/qtime)*qtime;
    cost=duration*split[sn].cost;
    cost=((cost+qcost)/qcost)*qcost;
    cost=MAX(cost,mincost)/1000;
   }
  }
 }
 return(cost);
}






static char * xnames[MAXPRIORITIES]=
{
 "Urgent",
 "Important",
 "Standard",
 "Offpeak",
 "Economy",
 "Cheap",
 "Overnight",
};


char * priorityname(int priority)
{
 priority=MIN(MAXPRIORITIES,priority);
 return(xnames[priority]);
}


int prioritynametopriority(char * name)
{
 int n;

 for(n=0;n<MAXPRIORITIES;n++)
 {
  if(!cstrcmp(xnames[n],name)) return(n);
 }
 return(0);
}







static genmenufn pfn;


void poppriority(genmenufn fn,int value)
{
 int i;

 pfn=fn;

 for(i=0;i<MAXPRIORITIES;i++) tickst(schedpri_menu,i,i==value);
 popmenu(schedpri_menu);
}


void decodepriority(int m)
{
 int value;
 int i;

 if(m>=0 && m<MAXPRIORITIES)
 {
  value=pfn(m);
  for(i=0;i<MAXPRIORITIES;i++) tickst(schedpri_menu,i,i==value);
 }
}



static genmenufn bfn;


static void setpopbandmenu(int value)
{
 int i;

 for(i=-1;i<bands;i++) tickst(band_menu,i+1,i==value);

 popmenu(band_menu);
}


void popband(genmenufn fn,int value)
{
 bfn=fn;

 clearusermenus();
 band_menu=(int*)setupbandmenu();
 if(band_menu)
 {
  setpopbandmenu(value);
  popmenu(band_menu);
 }
}


void decodebandmenu(int m)
{
 int value;

 m--;

 if(m>=-1 && m<bands)
 {
  value=bfn(m);
  setpopbandmenu(value);
 }
}

