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

#include "header.h"
#include "Game.h"
#include "Win.h"
#include "Dictionary.h"
#include "Timer.h"
#include "Hash.h"

extern gamestate_t state;
extern Win *win;
extern Dictionary dict;

Hash *hash;

Game::Game(char *word)
{
  
     srand( time(NULL) ); // Seed random number generator
     memset(letter, 0, sizeof(letter));
     memset(userword, 0, sizeof(userword));

     hash = new Hash(101);

     score = 0;
     words = 0;
     pos = 0;

     nineword = word;
     shuffledword = shuffle(word);
     state = GS_PLAYING;

}

Game::~Game(void)
{

     cout << "You got " << score << " words\n";
     cout << "The Nineword was " << nineword << "\n";
     cout << "***************************************" << endl;
     delete hash;
     free(nineword); /* Which was strdup'd */
     free(shuffledword);

}


#define ITERATIONS 3
/* strfry() is a GNU-ism, so I have to make my own shuffler */
char *Game::shuffle(char *word)
{
     char *str, c;
     int i, j, k;
     int length;
     
     str = (char *)strdup(word);
     length = strlen(str);

     //printf("Origional string = %s\n", str);

     for( int i=0 ; i<ITERATIONS ; i++ ) {
	  for( j=0 ; j<length ; j++ ) {
	       k = random()%length;
	       // Swap str[j] & str[k]
	       c = str[j];
	       str[j] = str[k];
	       str[k] = c;
	  }
	  //printf("Shuffled string = %s\n", str);
     }

     return str;

}


void Game::play(void)
{
     Point point;
     Timer timer(10);

     draw_board( shuffledword );
     set_score(0);
     while( state == GS_PLAYING ) {
	  if( win->button_click(&point) )
	       handle_click(point);
	  timer.delay();
     }

     //printf("game::play, state = %d\n", state);

}


void Game::draw_board(char *word)
{
     char prompt[] = "Word: ";
     char letter[2] = { 0, 0 };
     int x, y;
     int i, j, k;

     for( y=0 ; y<3 ; y++ ) {
	  for( x=0 ; x<3 ; x++ ) {
	       i = y * 3 + x;
	       j = x * BUTTON_W;
	       k = y * BUTTON_H;
	       /* Copy to null-terminated string */
	       letter[0] = word[i];
	       if( i == 4 ) {  /* Middle square */
		    win->clear_area(j, k, BUTTON_W, BUTTON_H, BLACK);
		    win->print(letter, j + 24, k + 18, WHITE);
	       } else {
		    win->clear_area(j, k, BUTTON_W, BUTTON_H, WHITE);
		    win->print( letter, j + 24, k + 18);
	       }
	  }
     }

     /* Horizontal dividers */
     for( int y=1 ; y < 3 ; y++ )
	  win->draw_line( 0, y * BUTTON_H, BOARD_H, y * BUTTON_H);
     /* Verticle dividers */
     for( int x=1 ; x < 3 ; x++ )
	  win->draw_line( x * BUTTON_W, 0, x * BUTTON_W, BOARD_W);
     
     /* Border */
     win->draw_line( 0, 0, BOARD_W, 0, 3); //Top
     win->draw_line( 0, BOARD_H - 1, BOARD_W, BOARD_H - 1, 3); //Bottom
     win->draw_line( 0, 0, 0, BOARD_H, 3); //Left
     win->draw_line( BOARD_W, 0, BOARD_W, BOARD_H, 3); //Right

     /* Bottom Box */
     win->clear_area(0, BOARD_H, BOARD_W + MENU_W, TB_H, WHITE);
     text_pos = win->text_width(prompt);
     win->print(prompt, 0, BOARD_H);

     win->update();

}


void Game::draw_cross(int i)
{
     int x0, y0, x1, y1;

     x0 = i % 3;
     y0 = i / 3;

     x1 = x0 + 1;
     y1 = y0 + 1;

     /* Convert to pixels */
     x0 *= BUTTON_W;
     y0 *= BUTTON_H;
     x1 *= BUTTON_W;
     y1 *= BUTTON_H;

     win->draw_line(win->buf, x0, y0, x1, y1, 2, i==4? WHITE : BLACK );
     win->update();

}


void Game::letter_click(int i)
{
     char str[2];

	 if( i < 0 || i >= 9 ) { /* Out of range */
		cout << "letter value " << i << " is out of range!" << endl;
		return;
	 }

     if( letter[i] == 0 ) {
	  str[0] = shuffledword[i];
	  userword[pos] = str[0];
	  win->print(str, text_pos, BOARD_H);
	  text_pos += win->text_width(str);
	  pos++;
	  fflush(NULL);
	  letter[i] = 1;
	  draw_cross(i);
     }

}


void Game::set_score(int s)
{
     char buf[8];
     int x;

     snprintf(buf, 8, "%d", s);
     score = s;
     x = BOARD_W + MENU_W - win->text_width(buf);
     win->clear_area(BOARD_W, BOARD_H, MENU_W, TB_H, WHITE);
     win->print(buf, x, BOARD_H);
     win->update();

}


void Game::clear_board(void)
{

     memset(letter, 0, sizeof(letter));
     memset(userword, 0, sizeof(userword));
     pos = 0;
     draw_board(shuffledword);
     set_score(score);

}


void Game::handle_click(Point point)
{

		if( point.y > BOARD_H )
				return; /* Who cares? */

     /* Menu */
		if( point.x >= BOARD_W ) {
				if( point.y < BUTTON_H ) {
						check_word(userword);
				} else if( point.y < BUTTON_H * 2 ) {
						clear_board();
				} else if( point.y < BUTTON_H * 3 ) {
						state = GS_RESTART;
				}
		} else {
				int letter = (point.y/BUTTON_H)*3 + point.x/BUTTON_W;
				letter_click(letter);
		}

}


/* Check to see if word is legit */
bool Game::islegit(char *word)
{
     int i, len;

     len = strlen(word);

     if( len < 4 ) {
	  //cout << "TOO SHORT!\n" << endl;
	  return false;
     }

     for( i=0 ; i<len ; i++ ) {
	  if( word[i] == shuffledword[4] )
	       return true;
     }

     //cout << "Doesn't contain center letter!\n" << endl;
     return false;

}


void Game::check_word(char *word)
{

     if( islegit(word) ) {
	  if( dict.isaword(word) ) {
	       if( hash->lookup(word) )
		    printf("Already found %s\n", word);
	       else if( hash->install(word) == NULL ) {
		    printf("Error installing %s on hashtable\n", word);
		    exit(1);
	       } else {
		    set_score(++score);
		    cout << score << ") " << word;
		    if( strlen(word) == 9 )
			 cout << " <-- NINEWORD";
		    cout << endl;
	       }
	  } else {
	       /* FIXME: Add a check to see if it's an actual word,
		  just not in the dictionary?? */
 	       //cout << "Not found in dictionary!" << endl;
	  }
     }
     
     clear_board();

}
