#ifndef cgrid_h
#define cgrid_h

#include "ForwardDeclarations.h"
#include "cGameMode.h"
#include <queue>
#include <iostream>
#include <String>
using namespace std;

enum BLOCK_TYPE {	RED_BLOCK, BLUE_BLOCK, GREEN_BLOCK, ORANGE_BLOCK, PURPLE_BLOCK, EMPTY_BLOCK,
                        RED_EXPLODER, BLUE_EXPLODER, GREEN_EXPLODER, ORANGE_EXPLODER, PURPLE_EXPLODER, NULL_TYPE };

class cGrid
{
public:
    cGrid();

    void draw();
    
    const static int gridXSize_ = 7;
    const static int gridYSize_ = 12;

	int translategrid_;

	void setTranslation(int translate);
	
	void makeAttackRows(int n); // adds rows of random blocks to the top of this grid and then sets mode to fall
								// n is the number of blocks destroyed in a single attack and n/10 rows of blocks get dumped
	
	void reset();				// reset for new game

    class cBlock
    {
    public:
        static BLOCK_TYPE getRandomBlockType();		// returns a random type of block
        
        cBlock();
        
        cGrid* grid_;	// the grid this block is in
        
        int x_, y_; 	// coordinates in grid
        
		int translategrid_;

        float size_; // for the purposes of drawing
        
        BLOCK_TYPE type_;
        
        bool canMove(int dx, int dy);
        bool move(int dx, int dy);
        
        void draw(int translate);
        void drawGem();
        void drawExploder();
		void drawEmpty();


    };
    
    cBlock blocks_[gridXSize_][gridYSize_];

	////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    
		GAME_MODE mode_;

		void randomizeDropBlocks();					// reset the drop blocks to the top of the screen, randomize types
		bool moveDroppingBlocks(int dx, int dy);	// returns true if the block could be moved, false otherwise
		bool rotateDroppingBlocksR();				// rotate right
		bool rotateDroppingBlocksL();				// rotate right
		void collideBlocks();						// sticks the dropping blocks into the grid and rerandomizes them 
		//void dropBlocks();							// respond to input and automatically fall in block dropping mode
    
		void explode();								// handle explosions of blocks
    
		bool neighborIsSameType(cBlock* p, int dx, int dy); // returns true if neighbor is same type
		// adds p's neighbor to the explosion queue if it exists and is the same type as p
		// return true if the neighbor was added, false otherwise
		bool addNeighborToExplosionQueue(cGrid::cBlock* p, int dx, int dy);	
                                                
		void startExplosions();			// find each explosion type box and adds appropriate neighbors to explosion queue
    
		void gridFall();				// move blocks in grid that have nothing under them down
    
		void update();				// gets time difference between last update call. causes blocks to move down with time

		
		cBlock droppingBlock1_, droppingBlock2_;
    
		queue<cBlock*> explosionQueue_;

		float timeSinceDrop_;			// time since game automatically moved a piece down
		float timeToDrop_;				// how often we cause the block to move down
		float timeToFall_;				// time inbetween making blocks fall due to gravity
		float timeSinceMove_;			// time since the dropping blocks last moved under user control
		float timeToMove_;				// time between dropping blocks moves under user control
		float timeSinceExplode_;		// time since a block last exploded in an explosion chain
		float timeToExplode_;			// time between explosions in an explosion chain
    
		int score_;						// the player's score
		
		int attackScore_;				// score within current explosion


//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
};

#endif