#include <iostream>
#include <sstream>
#include <ctime>
#include <SFML/Graphics.hpp>

using namespace sf;
using namespace std;

enum Gem{ gemEmpty, gemBlue, gemGreen, gemOrange, gemPurple, gemRed, 
		gemWhite, gemYellow };

#define GETPOS(i, j) Vector2f(BOARD_OFFSET_X + i*GEM_WIDTH, BOARD_OFFSET_Y + j * GEM_WIDTH )

bool removeMatch( Gem squares[][8] )
{
	int k;
	bool removed = false;
	Gem copy[8][8];
	memcpy( copy, squares, 64*sizeof(Gem) );

	// First, we check each row (horizontal)
    for(int y = 0; y < 8; ++y){
        for(int x = 0; x < 6; ++x){

			int match = 0;

            for(k = x+1; k < 8; ++k){
                if(squares[x][y] == squares[k][y] &&
                   squares[x][y] != gemEmpty){
                    match++;
                }else{
                    break;
                }
            }

            if(match >= 2){
                for(int z = x; z <= x + match; z++ ) {
					squares[z][y] = gemEmpty;
					removed = true;
				}
            }

            x = k - 1;
        }   
    }

    for(int x = 0; x < 8; ++x){
        for(int y = 0; y < 6; ++y){

            int match = 0;

            for(k = y + 1; k < 8; ++k){
                if(copy[x][y] == copy[x][k] &&
                   copy[x][y] != gemEmpty){
                    match++;
                }else{
                    break;
                }
            }

            if(match >= 2){
                for(int z = y; z <= y + match; z++ ) {
					squares[x][z] = gemEmpty;
					removed = true;
				}
            }

            y = k - 1;
        }
    }
	return removed;
}

void dropGems( Gem board[][8] )
{
	for(int x = 0; x < 8; ++x){
		int skip = 0;
        for(int y = 7; y >= 0; --y){
			if( board[x][y] == gemEmpty ) {
				skip++;
				continue;
			} else if( skip > 0 ) {
				// fall skip 
				board[x][y+skip] = board[x][y];
				board[x][y] = gemEmpty;
			}
		}
	}

}

void generateGems( Gem board[][8] )
{
	int removedBlockCnt = 0;
	for(int x=0; x < 8; x++ ) {
		for( int y=0; y < 8; y++ ) {
			if( board[x][y] == gemEmpty ) {
				board[x][y] = (Gem)(rand() % 4 + 1);
				removedBlockCnt++;
			}
		}
	}
	//if( g_count2score == false ) {
	//	g_count2score = true;
	//} else
	//	g_score += removedBlockCnt * 5 * g_multiplier++;
}


int main()
{
	RenderWindow window(VideoMode(800, 600), "Bejeweled");
	window.setFramerateLimit(60);

	// Load backgroun image
	Texture txBackground;
	txBackground.loadFromFile("resources/Background.png");
	Sprite spBackground(txBackground);

	// my cursor
	Texture txCursor;
	txCursor.loadFromFile("resources/handCursor.png");
	Sprite spCursor( txCursor );
	spCursor.setOrigin( 3, 3 );
	window.setMouseCursorVisible(false);

	// menu text
	Font fnMenu;
	fnMenu.loadFromFile("resources/fNormal.ttf");

	Text ttExit;
	ttExit.setFont( fnMenu);
	ttExit.setCharacterSize( 50 );
	ttExit.setColor( Color::White );
	ttExit.setPosition( 30, 500 );
	ttExit.setString( "EXIT" );

	// Create Model for board
	Gem b[8][8];
	//srand( (unsigned int) time(0) );
	srand(1); // for debugging

	// Generate initial gems
	for( int i=0; i<8; i++ )
		for( int j=0; j<8; j++ )
			b[i][j] = Gem( rand() % 4 + 1 );

	// Create gem images
	Texture txBlue;
	txBlue.loadFromFile( "resources/gemBlue.png" );
	//Sprite spBlue( txBlue );

	Texture txGreen;
	txGreen.loadFromFile( "resources/gemGreen.png" );
	//Sprite spGreen( txGreen );

	Texture txOrange;
	txOrange.loadFromFile( "resources/gemOrange.png" );
	//Sprite spOrange( txOrange );

	Texture txPurple;
	txPurple.loadFromFile( "resources/gemPurple.png" );
	//Sprite spPurple( txPurple );

	Texture txRed;
	txRed.loadFromFile( "resources/gemRed.png" );
	//Sprite spRed( txRed );

	Texture txWhite;
	txWhite.loadFromFile( "resources/gemWhite.png" );
	//Sprite spWhite( txWhite );

	Texture txYellow;
	txYellow.loadFromFile( "resources/gemYellow.png" );
	//Sprite spYellow( txYellow );

	Texture txEmpty;

	// Board Geometry
	const int BOARD_OFFSET_X = 241;
	const int BOARD_OFFSET_Y = 36;
	const int GEM_WIDTH = 65;
	Texture gemtex[8] = { txEmpty, txBlue, txGreen, txOrange, txPurple, 
							txRed, txWhite, txYellow };
	int debugStep = 0;

	while( window.isOpen() ) {

		Event e;
		while( window.pollEvent(e) ) {
			if( e.type == Event::Closed )
			{
				window.close();
			}
			else if( e.type == Event::MouseButtonPressed 
						&& e.mouseButton.button == Mouse::Left )
			{
				if( ttExit.getGlobalBounds().contains( 
								e.mouseButton.x, e.mouseButton.y ) ) {
					window.close();
				}
			}
			else if (e.type == Event::KeyPressed ) {
				if( e.key.code == Keyboard::Space )
					debugStep++;
			}
		}
		// model update
		if( debugStep % 3 == 1 ) removeMatch( b );
		if( debugStep % 3 == 2 ) dropGems( b );
		if( debugStep % 3 == 0 ) generateGems( b );

		window.clear();
		// draw..
		window.draw(spBackground);

		// draw gems
		for( int i=0; i<8; i++ ) {
			for( int j=0; j<8; j++ ) {
				// draw b[i][j]
				if( b[i][j] == gemEmpty )
					continue;
				Sprite agem( gemtex[ b[i][j] ] );
				agem.setPosition( GETPOS(i, j) );
				window.draw( agem );
			}
		}

		// draw menu
		window.draw(ttExit);

		// set mouse position
		spCursor.setPosition(static_cast<Vector2f>(Mouse::getPosition(window)) );
		window.draw(spCursor);
		window.display();
	}

	return 0;

}
