#include <bwio.h>
#include <error.h>
#include <hash-table.h>
#include <tools.h>

int Alpha2Num(char a){
  if((a<='Z' && a>='A')) return ((a-'A')+10);
  if((a<='z' && a>='a')) return ((a-'a')+26+10);
  if((a<='9' && a>='0')) return (a-'0');
  return ILLEGAL_NAME;
}


void Hash(HT* Table,char* Str, int Len,int *R1,int *R2){
  int i = 0;
  int h1 = 0;
  int h2 = 0;
  int tempNum;
  int MagicNumber = Table->size;
  char ReadIn;
  for(;i<Len;i++){
    ReadIn = Str[i];
    if(ReadIn == 0) break;
    tempNum = Alpha2Num(ReadIn);
    if(tempNum == ILLEGAL_NAME) break;
    h1 *= 62;
    h2 *= 62;
    //if(tempNum == ILLEGAL_NAME)
    h1 += tempNum;
    h2 += tempNum;
    h2 /= MagicNumber;
    h1 %= MagicNumber;
    h2 %= MagicNumber;
  }
  *R1 = h1;
  *R2 = h2;
}
    
int InsertTo(HT* Table, int Tid, char* Str, int Len){
  int h1,h2;
  int FakeAddr = (int)(Table->NameSequence);
  Hash(Table,Str,Len,&h1,&h2);
  int returnIndex = 0;
  int index2 = (index2)%(Table->size);
  //bwprintf(COM2,"InserTo: h1:%d, h2:%d\n\r",h1,h2);
  if(Table->TidSequence[h1]!=-1 && Table->TidSequence[index2]!=-1)return HT_NOSLOT;
  //bwprintf(COM2,"InsertTo: str: %s\n\r",Str);
  if(Table->TidSequence[h1] == -1){
    Table->TidSequence[h1] = Tid;
    FakeAddr = FakeAddr+(h1*(NAME_LENGTH_MAX+1));
    returnIndex = h1;
    stringCopy((char *)FakeAddr,Str,Len);
    bwprintf(COM2,"InsertTo: index %d, fakeaddr %d, string: %s\n\r",returnIndex,FakeAddr, (char *)FakeAddr);
  }else if(Table->TidSequence[index2] == -1){
    returnIndex = index2;
    Table->TidSequence[index2] = Tid;
    FakeAddr = FakeAddr+((index2)*(NAME_LENGTH_MAX+1));
    stringCopy((char *)FakeAddr,Str,Len);
    
    bwprintf(COM2,"InsertTo: index %d, fakeaddr %d, string: %s\n\r",returnIndex, FakeAddr,(char *)FakeAddr);
  }
  return returnIndex;
}

int Lookup(HT* Table,char* Str, int Len){
  bwprintf(COM2,"Lookup: Str: %s\n\r",Str);
  int h1,h2;
  //bwprintf(COM2,"Hash: before hash\n\r");
  Hash(Table,Str,Len,&h1,&h2);
  int FakeAddr = (int)(Table->NameSequence);
  FakeAddr +=(h1 *(NAME_LENGTH_MAX + 1));
  //bwprintf(COM2,"Hash: after hash, h1: %d, addr2: %d\n\r",h1,((char *)(FakeAddr)));
  int result = stringCompare((char *)(FakeAddr),Str);
  bwprintf(COM2,"lookup: index %d, fakeaddr %d, string: %d\n\r",h1, FakeAddr,(char *)FakeAddr);
  int index2 = (h1+h2)%(Table->size);
  //bwprintf(COM2,"Hash: after compare, result: %d\n\r",result);
  if(result==0){
    return (Table->TidSequence)[h1];
  }else{
    FakeAddr = (int)(Table->NameSequence);
    FakeAddr = ((index2)*(NAME_LENGTH_MAX+1));
    result = stringCompare((char *)FakeAddr,Str);
    bwprintf(COM2,"Lookup: index %d, fakeaddr %d, string: %d\n\r",index2, FakeAddr,(char *)FakeAddr);
    if(result == 0) return (Table->TidSequence)[index2];
  }
  return -1;
}