#include <allegro.h>
#include <stdio.h>
#include "tankchaser.h"
#include "sounds.h"

#define MENU      0
#define SUB_MENU1 1
#define SUB_MENU2 2
#define GAME_RUN  3
#define EXIT -1

#define TO_10     1
#define TIME_ATTACK 2

#define START_GAME 0
#define EXIT_GAME 1

#define DESERT 10
#define RUSTY  11
#define URBAN  12
#define TECHNO 13




//finish initializing starting variables
void deinit(); //voids the deinit function, a bit of a waiste.

volatile long speed_counter = 0; // A long integer which will store the value of the timer used in the program.  COntrols the program cycle.
int frame_counter = 0; // A counter for which frame to draw. keeps track of time passed.
                                             // speed counter.
void increment_speed_counter() // A function to increment the speed counter
{
  speed_counter++; // This will just increment the speed counter by one. :)
}
END_OF_FUNCTION(increment_speed_counter); // Make sure you tell it that it's the end of the
                                                                 // function
 
 

int main(int argc, char *argv[]) {
	//Initialize starting variables
//main game variables
    int game_on = TRUE;
    
    int score=0;                                    //player score
    int g_time=0;                                   //timer variable used by the TO_10 game mode
    char score_string[24]="Score: ";                //String used by the win message in TO_10
    char score_number[24]="0";                      //Defaults the score string to 0
    char time_string[24];                           //Dummy string used to hold the the timer variable
    char time_base_string[36]= "It took you";       //Starter for the timer string
    char score_sting[12];
    int angle=0;                                    //angle determining rotation of tank.  Decimal angle system, only -255 to 255
    int win = FALSE;                                //sets the variable win to false
    int background=DESERT;                          //sets the default background variable
    
    int runs=0;                                     //sets the repeater variable for the menus to 0, prevents the menus from going by too fast
    //menu variables
    int mode=MENU;                                  //default mode, can be altered for debugging, MENU, SUB_MENU1, SUB_MENU2, GAME_RUN
    int stage=NULL;                                 //default stage, TO_10 or TIME_ATTACK, set to NULL to prevent
    int choice=START_GAME;                          //default choice for the first menu, neccasary
    
    //bitmap variables
    int tank_x = 0; //these hold the tank's x and y screen coordinates
    int tank_y = 50;
    
    int block_x=100;//these hold the starting coordinates of the block, only the first time through
    int block_y=100;
    
    int rad_x=100 ;//set the starting location of the radiation symbol
    int rad_y=200 ;
    
    //bitmap initializers
    BITMAP *tank = NULL; //Declare a BITMAP called tank, setting it to NULL
    BITMAP *block = NULL; //Declare a BITMAP called block, setting it to NULL
    BITMAP *back = NULL; //declares the background bitmap pointer
    BITMAP *score_block = NULL; // declares the score_block bitmap
    BITMAP *game_win = NULL;
    BITMAP *timer_block = NULL;
    
    BITMAP *title = NULL; //title bitmap declaration
    BITMAP *rad = NULL;   //radiation bitmap declaration
    BITMAP *start = NULL; //starting page bitmap declaration
    BITMAP *sub_1 = NULL; //SUB_MENU1 bitmap
    BITMAP *sub_2 = NULL; //SUB_MENU2 bitmap
	
	int depth, res;  //declares the color depth and resolution variables
	allegro_init();  //initializes the Allgro specific functions
	install_timer();  //installs the timer
	install_keyboard();  
	install_mouse();
	depth = desktop_color_depth();  //sets depth = the return value of function desktop_color_depth
	if (depth == 0) depth = 32;  //sets the color depth to 32
	set_color_depth(32);
	res = set_gfx_mode(GFX_AUTODETECT_WINDOWED, 640, 480, 0, 0); //sets the graphics mode
	install_sound(DIGI_AUTODETECT,MIDI_AUTODETECT,NULL);
	if (res != 0) {    //error checking for the resollution
		allegro_message(allegro_error);
		exit(-1);
                 }
	
	
	LOCK_VARIABLE(speed_counter); //Used to set the timer - which regulates the game's
    LOCK_FUNCTION(increment_speed_counter);//speed.
    
    install_int_ex(increment_speed_counter, BPS_TO_TIMER(60));//Set our BPS, our the speed of our game
	
	BITMAP *buffer = NULL; // Declare a BITMAP called buffer.
	buffer = create_bitmap(640,480); //Create an empty bitmap.
	
	//error checking
	if (buffer==NULL){
         set_gfx_mode(GFX_TEXT,0,0,0,0);
         allegro_message("Could not create buffer!");
         exit(EXIT_FAILURE);
                     }
	DATAFILE *graphics=NULL;
	DATAFILE *sounds = NULL;
	
	sounds = load_datafile("sounds.dat");
    graphics = load_datafile("graphics.dat");
	
    //loads the game bitmaps
    tank = (BITMAP*) graphics[d_tank].dat;
    block = (BITMAP*) graphics[d_block].dat;
    score_block = (BITMAP*) graphics[d_score_block].dat;
    game_win = (BITMAP*) graphics[d_win].dat;
    timer_block = (BITMAP*) graphics[d_timer].dat;
    
    title = (BITMAP*) graphics[d_title].dat;
    rad = (BITMAP*) graphics[d_rad].dat;
    start = (BITMAP*) graphics[d_start].dat;
    sub_1 = (BITMAP*) graphics[d_sub_menu1].dat;
    sub_2 = (BITMAP*) graphics[d_sub_menu2].dat;
    
    if (tank==NULL){
         set_gfx_mode(GFX_TEXT,0,0,0,0);
         allegro_message("Could not create tank sprite!");
         exit(EXIT_FAILURE);
                     }
                     
    if (block==NULL){
         set_gfx_mode(GFX_TEXT,0,0,0,0);
         allegro_message("Could not create block sprite!");
         exit(EXIT_FAILURE);
                     }                         
    //bounding box data, for collision detection
    
    int tank_bb_left = tank_x;
    int tank_bb_top = tank_y;
    int tank_bb_right = (tank_bb_left + tank->w);
    int tank_bb_bottom = (tank_bb_top + tank->h);
    
    int block_bb_left = block_x;
    int block_bb_top = block_y;
    int block_bb_right = (block_bb_left + block->w);
    int block_bb_bottom = (block_bb_top + block->h);
    
    int show_bbox = FALSE;
    //mode=MENU;
    
    int collision = FALSE;
    win = FALSE;
    
    choice=START_GAME;    
         
	while (game_on == TRUE) {
    
          
          while(speed_counter > 0){
     
		  if (mode==MENU){
             //restores game variables to default in event of a game restart.
             score=0;
             frame_counter=0;
             
             tank_x=0;
             tank_y=50;
             
             block_x=rand()%600;
             block_y=rand()%400;
             
             sprintf(score_number, "%i", score);
             
             //Begin setting coordinates of the radiation symbol
             
             if (choice==START_GAME){
                rad_x=95;
                rad_y=220;
                }
             
             if (choice==EXIT_GAME){
                rad_x=115;
                rad_y=305;
                }
             
             //Input and enter blocks
             
             if(key[KEY_DOWN] && choice==START_GAME){
             choice=EXIT_GAME;
             }
             
             else if(key[KEY_UP] && choice==EXIT_GAME){
             choice=START_GAME;
             }
             
             if(runs>5){
             if(key[KEY_ENTER] && choice==START_GAME){
             mode=SUB_MENU1;
             play_sample((SAMPLE*)sounds[d_select].dat,255,255,1000,0);
             clear_bitmap(buffer);
             choice=DESERT;
             }
             runs=0;
             }
             
             if(key[KEY_ENTER] && choice==EXIT_GAME){
             mode=EXIT;
             }             
             speed_counter--;
        }
        else if (mode ==SUB_MENU1){
             
              //Begin setting coordinates of the radiation symbol
             
             if (choice==DESERT){
                 rad_x=100;
                 rad_y=205; 
                 }
             
             if (choice==URBAN){
                rad_x=100;
                rad_y=275;
                }
                
             if (choice==RUSTY){
                rad_x=320;
                rad_y=205;
                } 
                
             if (choice==TECHNO){
                rad_x=320;
                rad_y=275;
                }                                                             
             
             //Begin Input
             
             if (key[KEY_DOWN] && choice==DESERT){
                choice=URBAN;
                }
             if (key[KEY_RIGHT] && choice==DESERT){
                choice= RUSTY;
                }
             if (key[KEY_UP] && choice==URBAN){
                choice= DESERT;
                }
             if (key[KEY_RIGHT] && choice==URBAN){
                choice=TECHNO;
                }
             if (key[KEY_DOWN] && choice==RUSTY){
                choice=TECHNO;
                }
             if (key[KEY_LEFT] && choice==RUSTY){
                choice=DESERT;
                }
             if (key[KEY_UP] && choice==TECHNO){
                choice=RUSTY;
                }
             if (key[KEY_LEFT] && choice==TECHNO){
                choice=URBAN;
                }
                
             //Begin enter section.                 
             
             if(runs>10){
             
             if (key[KEY_ENTER] && choice==DESERT){
             background=DESERT;
             mode=SUB_MENU2;
             choice=TO_10;
             runs=0;
             }
             if (key[KEY_ENTER] && choice==RUSTY){
             background=RUSTY;
             mode=SUB_MENU2;
             choice=TO_10;
             runs=0;
             }
             
             if (key[KEY_ESC]){
                mode = MENU;
                choice = EXIT_GAME;
                }
             
             }
             //Speed must be returned to 0 in order for drawing to occur.
             speed_counter--;
          }
        else if (mode ==SUB_MENU2){
            // choice=TO_10;
             if(choice==TO_10){
               rad_x=190;
               rad_y=240;
               }
               
             if(choice==TIME_ATTACK){
               rad_x=130;
               rad_y=320;
               }
                 
             if (key[KEY_DOWN]){
                choice=TIME_ATTACK;
                }
             if (key[KEY_UP]){
                choice=TO_10;
                }                
                 
             if (runs>10){
             if (key[KEY_ENTER] && choice==TO_10){
                mode=GAME_RUN;
                stage=TO_10;
                runs=0;
                }
                
                
             if (key[KEY_ENTER] && choice==TIME_ATTACK){
                   mode=GAME_RUN;
                stage=TIME_ATTACK;
                g_time=45;
                runs=0;
                frame_counter = 0;
                }
                }   
                
             if (key[KEY_ESC]){
                mode = MENU;
                choice = EXIT_GAME;
                }
             speed_counter--;
             }
             
          
          
          if (mode==EXIT){
             return -1;
             }
          
        else  if (mode==GAME_RUN){
         if(win==FALSE){ 
          if(key[KEY_RIGHT] && tank_x<=screen->w-50) // If the user hits the right key, change the picture's X coordinate
        {
           tank_x+=2; // Moving right so up the X coordinate by 1
           angle=64;
        }
         else if(key[KEY_LEFT] && tank_x>0) // Ditto' - only for left key
        {
           tank_x -=2; // Moving left, so lower the X coordinate by 1
           angle=-64;
        }
         else if(key[KEY_UP] && tank_y>=0) // If the user hits the up key, change the picture's Y coordinate
        {
           tank_y -=2; // Moving up, so lower the Y coordinate by 1
           angle=0;
        }
         else if(key[KEY_DOWN] && tank_y<=430) // Ditto' - only for down
        {
           tank_y +=2; // Moving down, so up the Y coordinate by 1
           angle=128;
        }
         if (key[KEY_ESC]){
            mode = MENU;
            stage = NULL;
            choice = EXIT_GAME;
        }
        }
                                
         tank_bb_left = tank_x;
         tank_bb_top = tank_y;
         tank_bb_right = (tank_bb_left + tank->w);
         tank_bb_bottom = (tank_bb_top + tank->h);
         
         block_bb_left = block_x;
         block_bb_top = block_y;
         block_bb_right = (block_bb_left + block->w);
         block_bb_bottom = (block_bb_top + block->h);   
         
         collision = FALSE;
         
         //checks for collisions, yeah its ugly.  Tests the corners of the of the tank to block
          if(
   (tank_bb_left >= block_bb_left) && (tank_bb_top >= block_bb_top) &&
   (tank_bb_left <= block_bb_right) && (tank_bb_top <= block_bb_bottom)
            ){
             collision = TRUE;
             }
   
          else if(
   (tank_bb_right <= block_bb_right) && (tank_bb_right >= block_bb_left) &&
   (tank_bb_top >= block_bb_top) && (tank_bb_top <= block_bb_bottom)
            ){
             collision = TRUE;
             } 
             
          else if(
   (tank_bb_left >= block_bb_left) && (tank_bb_left <= block_bb_right) &&
   (tank_bb_bottom <= block_bb_bottom) && (tank_bb_bottom >= block_bb_top)
            ){
             collision = TRUE;
             }
             
          else if(
   (tank_bb_right <= block_bb_right) && (tank_bb_right >= block_bb_left) &&
   (tank_bb_bottom <= block_bb_bottom) && (tank_bb_bottom >= block_bb_top)
            ){
             collision = TRUE;
             }
            //tests the block for collision with the tank 
          if(
   (block_bb_left >= tank_bb_left) && (block_bb_top >= tank_bb_top) &&
   (block_bb_left <= tank_bb_right) && (block_bb_top <= tank_bb_bottom)
            ){
             collision = TRUE;
             }
          
          else if(
   (block_bb_right <= tank_bb_right) && (block_bb_right >= tank_bb_left) &&
   (block_bb_top >= tank_bb_top) && (block_bb_top <= tank_bb_bottom)
            ){
             collision = TRUE;
             }
             
          else if(
   (block_bb_right <= tank_bb_right) && (block_bb_right >= tank_bb_left) &&
   (block_bb_bottom <= tank_bb_bottom) && (block_bb_bottom >= tank_bb_top)
            ){
             collision = TRUE;
             }
             
           if(
    (tank_bb_top > block_bb_top) && (tank_bb_bottom < block_bb_bottom) &&
    (block_bb_left > tank_bb_left) && (block_bb_right < tank_bb_right)
            ){
             collision = TRUE;
             }
             
           if(
    (block_bb_top > tank_bb_top) && (block_bb_bottom < tank_bb_bottom) &&
    (tank_bb_left > block_bb_left) && (tank_bb_right < block_bb_right)
            ){
            collision = TRUE;
             }
         
     
     if (collision==TRUE && frame_counter<=60){
                          block_x=rand()%600;
                          block_y=rand()%400;
                         }
     if(collision==TRUE){
                          block_x=rand()%600;
                          block_y=rand()%400;
                          score+=1;
                         }                     
     if(stage==TO_10){ 
     
     if (score>=10){
        win = TRUE;
        score=0;
        runs=0;
        }
      
     if (frame_counter==60)
        {
        g_time++;
        frame_counter=0; 
        } 
        } 
        
     if (stage==TIME_ATTACK){
        if (g_time==0){
        win = TRUE;
        
        runs=0;
        }
        
        if (frame_counter==60)
        {
        g_time--;
        frame_counter=0; 
        } 
        } 
         
         speed_counter --;
         frame_counter++;
        
         if (angle>=255){
                        angle=0;
                        }
         if(key[KEY_SPACE] &&win==TRUE){
         win=FALSE;
         clear_keybuf();
         g_time=0;
         mode=MENU;
         choice=START_GAME;
         stage=NULL;
         runs=0;
         
          }//closes mode game_run
        }//closes while statement
        if (mode==MENU){
             
            draw_sprite(buffer,title, 0, 0);
            draw_sprite(buffer,rad,rad_x,rad_y);
            draw_sprite(buffer,start,160,220);
            blit(buffer,screen,0,0,0,0,640,480);

         clear_bitmap(buffer);
         runs++;
         }

        else if (mode==SUB_MENU1){
           draw_sprite(buffer,title, 0, 0);
           draw_sprite(buffer,sub_1,130,100);
           draw_sprite(buffer,rad,rad_x,rad_y);
           blit(buffer,screen,0,0,0,0,640,480);
           
        clear_bitmap(buffer);
        runs++;
        }
        
        else if (mode==SUB_MENU2){
           draw_sprite(buffer,title, 0, 0);
           draw_sprite(buffer,rad,rad_x,rad_y);
           draw_sprite(buffer,sub_2,190,110);
           blit(buffer,screen,0,0,0,0,640,480);
           
        clear_bitmap(buffer);
        runs++;
        }
        
        else if (mode==GAME_RUN){
            if(runs<1){
            
            if(background==DESERT){
            back = (BITMAP*) graphics[d_desert].dat;
            }
            else if(background==RUSTY){
            back = (BITMAP*) graphics[d_rusty].dat;
            }
            
            if (back==NULL){
             set_gfx_mode(GFX_TEXT,0,0,0,0);
             allegro_message("Could not create background!");
             exit(EXIT_FAILURE);
             }
             runs++;
             }
                            
        if(stage == TO_10){                
        
        if(collision==TRUE)
        {
          textprintf_ex(buffer, font, 0,0, makecol(0,0,0), -1, "Collision!");
          sprintf(score_number,"%i",score);                    
        }
        if(win==TRUE){
           sprintf(time_string, "%i",g_time);
           draw_sprite(buffer,back,0,0);
           draw_sprite(buffer,game_win,130,200);
           textprintf_ex(buffer, font, 290,230, makecol(0,0,0), -1, "You Won!");
           textprintf_ex(buffer, font, 240,240, makecol(0,0,0), -1, time_base_string);           
           textprintf_ex(buffer, font, 345,240, makecol(0,0,0), -1, time_string);
           textprintf_ex(buffer, font, 360,240, makecol(0,0,0), -1, " seconds!"); 
           textprintf_ex(buffer, font, 170,250, makecol(0,0,0), -1, " Press space to returnto the main menu.");
           blit(buffer,screen,0,0,0,0,640,480);
           readkey();
           
           clear_bitmap(buffer);
           runs++;
           }
           
        else{  
        draw_sprite(buffer,back,0,0); //goes into buffer first so it is drawn first(it's a background)
        draw_sprite(buffer,block,block_x,block_y); 
        rotate_sprite(buffer,tank , tank_x, tank_y, itofix(angle));  //adds the tank to the buffer
        draw_sprite(buffer,score_block,5,10);
        
        textprintf_ex(buffer, font, 70,25, makecol(255,255,255), -1, score_number);
        textprintf_ex(buffer, font, 20,25, makecol(255,255,255),-1,"Score: ");
        blit(buffer,screen,0,0,0,0,640,480);
        }
        
        }
        
        if(stage == TIME_ATTACK){                
        
        if(collision==TRUE)
        {
          textprintf_ex(buffer, font, 0,0, makecol(0,0,0), -1, "Collision!");
          sprintf(score_number,"%i",score);                    
        }
        if(win==TRUE){
           sprintf(score_string, "%i", score);
           draw_sprite(buffer,back,0,0);
           draw_sprite(buffer,game_win,140,200);
           textprintf_ex(buffer, font, 290,230, makecol(0,0,0), -1, "You Won!");
           textprintf_ex(buffer, font, 180,240, makecol(0,0,0), -1, "You stopped ");           
           textprintf_ex(buffer, font, 280,240, makecol(0,0,0), -1, score_string);
           textprintf_ex(buffer, font, 300,240, makecol(0,0,0), -1, "missles from launching. ");
           textprintf_ex(buffer, font, 170,250, makecol(0,0,0), -1, " Press space to return to the main menu.");
           blit(buffer,screen,0,0,0,0,640,480);
           readkey();
           
           clear_bitmap(buffer);
           runs++;
           }
           
        else{  
        draw_sprite(buffer,back,0,0); //goes into buffer first so it is drawn first(it's a background)
        draw_sprite(buffer,block,block_x,block_y);
        rotate_sprite(buffer,tank , tank_x, tank_y, itofix(angle));  //adds the tank to the buffer
        draw_sprite(buffer,score_block,5,10);
        draw_sprite(buffer, timer_block,310,12); 
        sprintf(time_string, "%i",g_time);
        textprintf_ex(buffer, font, 320,25, makecol(255,255,255),-1,time_string);
        textprintf_ex(buffer, font, 70,25, makecol(255,255,255), -1, score_number);
        textprintf_ex(buffer, font, 20,25, makecol(255,255,255),-1,"Score:");
        blit(buffer,screen,0,0,0,0,640,480);
        }
        
        }
    }
    
}
}
	deinit();
	unload_datafile(graphics);
	return 0;
}
END_OF_MAIN();




void deinit() {
	clear_keybuf();
}