#include "scr_Dictionary.h"

scr_Dictionary::scr_Dictionary(char* filename){
ifstream indexer(filename,ios::in|ios::bin);
unsigned long int size,count=0;
 indexer.read((char *)&size, 4);
 start=size-1;
 index = new unsigned long int[size];
 while(!indexer.eof()){
  indexer.read((char *)&index[count], 4);
  count++;
 }
}

scr_Dictionary::~scr_Dictionary(){
 delete[] index;
}

//tells a letter available to jump to, and returns stuff necessary to get to that point
//stuff:
//1-5: position in pointers/headers

inline char scr_Dictionary::GetSequence(unsigned long int stuff, char* build){
static char a,b;
 a=1; b=0;
 build[0]=Letter(stuff);
 if(IsTrailer(stuff)){
  unsigned long int temp=1;
  for(a=1;temp;a++,temp>>=5){
   if(a%6==1){
    temp=index[Jump(stuff)+b];
    b++;
   }
   build[a]=temp&31;
  }
 }
 build[a]='\0';
 return a;
}


char scr_Dictionary::Verify(char* input){
unsigned long int search=Jump(Start());
 if(PushString(input,search)){
  return(AreWords(search));
 }
 else return 0;
}

//point needs to be pointing to the first pointer of a sequence that PushString will try
char scr_Dictionary::PushString(char* input, unsigned long int& point){
char a=0,b=0,c[20],d,r=1;
 c[0]=0;
 while(r&&input[b]&&(input[b]>=Letter(point))){
  r=IsNextPointer(point);
  if(input[b]==Letter(point)){
   d=GetSequence(point,c);
   for(a=0;(input[b]==c[a])&&input[b];a++,b++);
   if(a){
    if(c[a]) return 0;
    else if(input[b]){
     d--;
     if(d) d=(d-1)/6+1;
     r=ArePointers(point);
     point=Jump(point)+d;
    }
   }
  }
  else point++;
 }
 if(input[b]){
  return 0;
 }
 else return 1;
}

inline void scr_Dictionary::PushStack(){
 stackheight++;
 stacklength[stackheight]=length;
 stackpos[stackheight]=pos;
}

inline void scr_Dictionary::PopStack(){
 length=stacklength[stackheight];
 pos=stackpos[stackheight];
 stackheight--;
}

char scr_Dictionary::Next(char* output, char& len, char& accept){
static char d,e;
 if(accept==0){
  if(nextone){
   PopStack();
   if(stackheight==0){
    output[0]=0;
    return 0;
   }
  }
  accept=length;
  nextone=0;
 }
 
 if(nextone>1){
  PopStack();
  if(stackheight==0){
   output[0]=0;
   return 0;
  }
  nextone=0;
 }
 d=GetSequence(pos,output);
 e=AreWords(pos);
 if(IsNextPointer(pos)){
  pos++;
  PushStack();
  pos--;
 }
 if(ArePointers(pos)){
  length+=d;
  nextone=1;
  pos=Jump(pos);
  d--;
  if(d) d=(d-1)/6+1;
  pos+=d;
 }
 else{
  nextone=IsNextPointer(pos);
  if(nextone==0){
   PopStack();
   if(stackheight==0){
    output[0]=0;
    return 0;
   }
  }
  else nextone=2;
 }
 len=length;
 return(e);
}

unsigned long int scr_Dictionary::Bridge(char* fore, char* aft){
unsigned long int point=Start(),travel,out=0;
char copy[15];
 if(fore[0]) point=Jump(point);
 if(PushString(fore,point)){
  if(ArePointers(point)){
   char q;
   for(q=0;aft[q];q++) copy[q+1]=aft[q];
   copy[q+1]='\0';
   q=IsTrailer(point);
   point=Jump(point);
   if(q){
    while(Raw(point)&(1<<31)) point++;
    point++;
   }
   do{
    q=IsNextPointer(point);
    travel=point;
    copy[0]=Letter(point);
    if(PushString(copy,travel)){
     if(AreWords(travel)) out+=(1<<(copy[0]-1));
    }
    point++;
   }while(q);
  }
 }
 return(out);
}
