#include "scr_LocalServer.h"
scr_LocalServer::scr_LocalServer(){
 //just for now
 BSIZE=15;
 TILENUM=7;
 BINGO=50;
 
 Dict = new scr_Dictionary("US_English_Dictionary.dic");
 Bag = new scr_Bag("US_English_Bag.txt");
 TheBoard = new scr_Board("Standard_Board.txt",Bag, Dict);
 curplayer=0;
 quit=1;
 totalplayers=0;
 numplayers=0;
 guillotine=0;
}

scr_LocalServer::~scr_LocalServer(){
 delete TheBoard;
 delete Dict;
 delete Bag;
 for(curplayer=0;curplayer<totalplayers;curplayer++)
  if(ThePlayaz[curplayer]) delete ThePlayaz[curplayer];
}

//1:Human
//2:Computer
//3:TCP/IP?

void scr_LocalServer::CreatePlayer(PLAYERTYPE type){
 switch(type){
  case HUMAN :{
   ThePlayaz[totalplayers] = new scr_HPlayer(TILENUM);
   break;
  }
 }
 curplayer=totalplayers;
 FillCurPlayerTiles();
 totalplayers++;
 numplayers++;
}

void scr_LocalServer::RunGame(){
int x,y,scores[10];
 for(curplayer=0;curplayer<totalplayers;curplayer++)
  ThePlayaz[curplayer]->InformInitialStats(totalplayers);
 curplayer=0;
 while(numplayers>1){
  ThePlayaz[curplayer]->GetData();
  if(guillotine){
   delete ThePlayaz[curplayer];
   ThePlayaz[curplayer]=0;
   guillotine=0;
  }
  if(ThePlayaz[curplayer]){
   //see if the player has any tiles left after refilling, if so, the game continues...but if not THEN IT ENDS!!!
   if(ThePlayaz[curplayer]->NumTiles()) NextPlayer();
   else break;
  }
  else NextPlayer();
 }
 if(numplayers>1){
  int victor=curplayer;
  for(x=0;x<totalplayers;x++)
   scores[x]=0;
  for(curplayer=0;curplayer<totalplayers;curplayer++){
   if(ThePlayaz[curplayer]){
    y=0;
    for(x=0;x<TILENUM;x++) y+=Bag->TileValue(ThePlayaz[curplayer]->GetTile(x));
    ThePlayaz[victor]->AddScore(y);
    ThePlayaz[curplayer]->AddScore(y*-1);
    scores[curplayer]=GetCurPlayerScore();
   }
  }
  for(curplayer=0;curplayer<totalplayers;curplayer++)
   if(ThePlayaz[curplayer]) ThePlayaz[curplayer]->InformFinalScores(scores);
 }
}

int scr_LocalServer::SubmitMove(scr_Move* move){
int result,counter;
char *used;
 switch(move->type){
  case play :{
   //check to see if the move is valid before we do anything
   //check the positioning, and check that the proper tiles were used
   int works=TheBoard->Valid(move->x,move->y,move->dx,move->input);
   used=DeterminePlayedTiles(move);
   if(works==0&&used[0]){
    //the player doesn't get to use his tiles again
    RemoveTiles(used,0);
    delete used;
    //if the player used all his tiles, he deserves his due
    if(ThePlayaz[curplayer]->NumTiles()==0) ThePlayaz[curplayer]->AddScore(BINGO);
    //get some new tiles
    FillCurPlayerTiles();
    //hey, its all about the score right?
    result=TheBoard->Score(move->x,move->y,move->dx,move->input);
    ThePlayaz[curplayer]->AddScore(result);
     //nice internal stuff; just run this function when the player makes a valid a move
    TheBoard->Integrate(move->x,move->y,move->dx,move->input);
   }
   else result=-1;
   break;
  }
  case exchange:{
   result=RemoveTiles(move->input,1);
   break;
  }
  case drop:{
   RequestCurPlayerDrop();
   result=1;
   break;
  }
  default :{
   result=0;
   break;
  }
 }
 for(counter=0;counter<totalplayers;counter++)
  if(ThePlayaz[counter]&&counter!=curplayer) ThePlayaz[counter]->Update(move,result);
 return(result);
}

char* scr_LocalServer::DeterminePlayedTiles(scr_Move* move){
int x=move->x, y=move->y;
char dx=move->dx, dy=((move->dx+1)&1);
char a,b,c=0,ismatch,compare;
char *used = new char[TILENUM+1];
char original[TILENUM];

 CopyCurPlayerTiles(original);
 for(a=0;move->input[a];a++){
  if(TranslateBoardLetter(x,y)!=move->input[a]){
   if(TranslateBoardLetter(x,y)){
    used[0]=0;
    return used;
   }
   
   if(move->input[a]<96) compare='*';
   else compare=move->input[a];

   for(b=0,ismatch=1;ismatch&&(b<TILENUM);b++){
    if(compare==original[b]){
     used[c]=compare;
     original[b]=0;
     c++;
     ismatch=0;
    }
   }
   if(ismatch){
    used[0]=0;
    return(used);
   }
  }
  x+=dx;  y+=dy;
 }
 return used;
}

int scr_LocalServer::RemoveTiles(char* remove, int exchange){
char a,b,c;
char *original;
unsigned long int *throwback;
 if(Bag->HowMany()>=TILENUM){
  original = new char[TILENUM];
  throwback = new unsigned long int[TILENUM];
  //initalize throwback to 0
  for(a=0;a<TILENUM;a++) throwback[a]=0;
  //get the player's original tiles
  CopyCurPlayerTiles(original);
  for(a=0;remove[a];a++){
   c=1;
   for(b=0;c&&(b<TILENUM);b++){
    if(remove[a]==original[b]){
     //if the letter desired to be thrown back and one in the rack coincide, then get the actual tile
     throwback[b]=ThePlayaz[curplayer]->GetTile(b);
     original[b]=0;
     c=0;
    }
    if(c&&b==TILENUM) return 0;
   }
  }
  //remove the offending tiles from the player's rack if the player wants them exchanged
  for(a=0;a<TILENUM;a++) if(throwback[a]) ThePlayaz[curplayer]->RemoveTile(a);
  if(exchange){
   //replace the discarded tiles with new ones
   FillCurPlayerTiles();
   //put the discarded tiles back in the bag
   for(a=0;a<TILENUM;a++) if(throwback[a]) Bag->PutTile(throwback[a]);
  }
  delete throwback;
  delete original;
  return 1;
 }
 else return 0;
}

void scr_LocalServer::RequestCurPlayerDrop(){
 guillotine=1;
 numplayers--;
}

void scr_LocalServer::GetCopyOfBoard(char** representation){
char x,y;
 for(x=0;x<BSIZE;x++){
  for(y=0;y<BSIZE;y++){
   if(TheBoard->Letter(x,y)){
    representation[x][y]=TranslateBoardLetter(x,y);
   }
   else{
    if(TheBoard->WordMult(x,y)>1) representation[x][y]=((TheBoard->WordMult(x,y)==2) ? '@' : '#');
    else{
     if(TheBoard->LetterMult(x,y)==1) representation[x][y]='-';
     else representation[x][y]=((TheBoard->LetterMult(x,y)==2) ? '2' : '3');
    }
   }
  }
 }
}
