$: << File.dirname(__FILE__)
require 'rubygems'
require 'gosu'
require 'chipmunk'
require 'spikes.rb'
require 'finish.rb'
require 'player.rb'
require 'map2.rb'
require 'score.rb'
require 'level3.rb'
require 'razor_fly.rb'

class Numeric
  def radians_to_vec2
    CP::Vec2.new(Math::cos(self), Math::sin(self))
  end
end

class Level2 < Gosu::Window
  attr_reader :map
  SUBSTEPS = 6
  SCREEN_HEIGHT = 770
  def initialize(username, lifeforce, score)
    super(640, 770, false, 60)
    @username = username
    @lifeforce = lifeforce
    @score = score
    self.caption = "Back To Black [#{@username}]"
    @sky = Gosu::Image.new(self, "media/Background2.png", true)
    @map = Map2.new(self, "media/Map2.txt")
    @plyr = Player.new(self, 220, 330)
    @plyr.levelno = 2
    # The scrolling position is stored as top left corner of the screen.
    @camera_x = @camera_y = 0
    @text_gameover = Gosu::Font.new(self, 'ArialBold', 35)
    @text_gameover2 = Gosu::Font.new(self, 'Arial', 15)
    @time_text = Gosu::Font.new(self, 'ArialBold', 20)
    @time = lifeforce
    @score_value = score    
   
    @power = 0
    @max_power = 60
    
    # Time increment over which to apply a physics "step" ("delta t")
    @dt = (1.0/60.0)
    
    # Create the Space and set its damping
    # A damping of 0.8 causes the player to bleed off his force and torque over time
    @space = CP::Space.new
    @space.damping = 0.9
    @space.gravity = CP::Vec2.new(0.0,80)
            
    @cannon_balls = Array.new
    @angle = 4.7; 
    
    #create the environment (segments) so that boulder bounce onto them   
    land_body = CP::Body.new((1.0/0.0),(1.0/0.0))

    verts1 = [
      CP::Vec2.new(0,225), #x1 first corner
      CP::Vec2.new(0,SCREEN_HEIGHT), #x2 second corner
      CP::Vec2.new(115,SCREEN_HEIGHT), #x3 third corner
      CP::Vec2.new(115,227) #x4 fourth corner
    ]    
    land_shape = CP::Shape::Poly.new(land_body, verts1, CP::Vec2.new(0,0))
    land_shape.collision_type = :land
    @shape = land_shape          
    @shape.u = 5.0 # friction
    @shape.e = 0.0 # bounce
    @space.add_static_shape(land_shape)

    verts2 = [
      CP::Vec2.new(115,227), #x1 first corner
      CP::Vec2.new(115,SCREEN_HEIGHT), #x2 second corner
      CP::Vec2.new(250,SCREEN_HEIGHT), #x3 third corner
      CP::Vec2.new(250,204) #x4 fourth corner
    ]
    land_shape = CP::Shape::Poly.new(land_body, verts2, CP::Vec2.new(0,0))
    land_shape.collision_type = :land
    @shape = land_shape
    @shape.u = 5.0 # friction
    @shape.e = 0.0 # bounce
    @space.add_static_shape(land_shape)

    verts3 = [
      CP::Vec2.new(250,204), #x1 first corner
      CP::Vec2.new(250,SCREEN_HEIGHT), #x2 second corner
      CP::Vec2.new(652,SCREEN_HEIGHT), #x3 third corner
      CP::Vec2.new(652,220), #x4 fourth corner
      CP::Vec2.new(460,160), #x5 fourth corner
      CP::Vec2.new(404,165) #x6 fourth corner
    ]
    land_shape = CP::Shape::Poly.new(land_body, verts3, CP::Vec2.new(0,0))
    land_shape.collision_type = :land
    @shape = land_shape
    @shape.u = 5.0 # friction
    @shape.e = 0.0 # bounce
    @space.add_static_shape(land_shape)

    verts4 = [
      CP::Vec2.new(652,220), #x1 first corner
      CP::Vec2.new(652,SCREEN_HEIGHT), #x2 second corner
      CP::Vec2.new(915,SCREEN_HEIGHT), #x3 third corner
      CP::Vec2.new(915,220)
    ]
    land_shape = CP::Shape::Poly.new(land_body, verts4, CP::Vec2.new(0,0))
    land_shape.collision_type = :land
    @shape = land_shape
    @shape.u = 5.0 # friction
    @shape.e = 0.0 # bounce
    @space.add_static_shape(land_shape)
    
    verts5 = [
      CP::Vec2.new(915,325), #x1 first corner
      CP::Vec2.new(915,SCREEN_HEIGHT), #x2 second corner
      CP::Vec2.new(1030,SCREEN_HEIGHT), #x3 third corner
      CP::Vec2.new(1030,327) #x4 fourth corner
    ]    
    land_shape = CP::Shape::Poly.new(land_body, verts5, CP::Vec2.new(0,0))
    land_shape.collision_type = :land
    @shape = land_shape          
    @shape.u = 5.0 # friction
    @shape.e = 0.0 # bounce
    @space.add_static_shape(land_shape)
         
  end
  
  def retry_game
    @plyr = Player.new(self, 220, 330)    
    @camera_x = @camera_y = 0
    @time = @lifeforce
    @lifeforce -= 200
    @score_value = @score
    @cannon_balls = Array.new
  end
  
  def save_score
    close    
    set_score(2000 + @time)  
    save_highscore(@username, @score_value)
    game_window = Score.new
    game_window.score_value = @score_value
    game_window.username = @username
    game_window.show    
  end
  
  def save_progress    
    close
    #serialize the player class
      
  end
  
  def load_level3
    close
    set_score(2000 + @time)     
    #load third stage        
    game_window = Level3.new(@username, @time, @score_value)
    game_window.show 
  end
  
  def update     
    if (@plyr.status == "alive")
      @time -= 1
        
      @plyr.check_time(@time)
      move_x = 0
      move_x = -2 if button_down? Gosu::KbLeft
      move_x = 2 if button_down? Gosu::KbRight
      @plyr.update(move_x)    
    end
    if (@plyr.status == "dead")
      @plyr.update(move_x)
    end  
    @plyr.detect_spikes(@map.spikes) #detect evil tiles      
    @plyr.detect_finish(@map.finish) #detect finsh  
          
    # Scrolling follows player
    @camera_x = [[@plyr.x - 320, 0].max, @map.width * 50 - 640].min
    @camera_y = [[@plyr.y - 240, 0].max, @map.height * 50 - 480].min  
      
    # Step the physics environment SUBSTEPS times each update
    SUBSTEPS.times do
      @space.step(@dt)                
    end
      
    if @power < @max_power      
      @power += 2
    end
    if @power == @max_power
      @power = 0
    end
    if @power > @max_power
      @power = 0
    end
    
  end
  
  def draw  
    @time_text.draw('life-force: ' + @time.to_s, 10,10,4,1,1,0xffd60606)
    @sky.draw 0, 0, 0    
    translate(-@camera_x, -@camera_y) do
      @map.draw
      @plyr.draw
       
      @cannon_balls.each do |cannon_ball|
        if (@plyr.status != "dead") && (@plyr.x < 1250)
          if cannon_ball.draw(@plyr.x, @plyr.y) == true
            @plyr.set_dead          
          end
        elsif (@plyr.x < 1250)
          cannon_ball.draw(@plyr.x, @plyr.y)
        end
      end
      
      if @power == 30
        #draw flies
        fly_body = CP::Body.new(10.0001, 10.0001)
        fly_shape = CP::Shape::Circle.new(fly_body, 28/2, CP::Vec2.new(0.0, 0.0))
        fly_shape.collision_type = :boulder

        @space.add_body(fly_body)
        @space.add_shape(fly_shape)
        @cannon_balls.push(Razor_fly.new(self, fly_shape, @angle, @power))
        
      end      
    end
    
    if (@plyr.status == "dead")
      @text_gameover.draw("Game Over", 260,260,4,1,1,0xffd60606)
      @text_gameover2.draw('[enter] to retry      [esc] to exit', 250,290,4,1,1,0xffd60606)      
    end   
    #check if end of stage
    if (@plyr.status == "Exit")
      @text_gameover.draw('Level Complete', 260,260,4,1,1,0xffd60606)
      @text_gameover2.draw('Procceed to next level? [Y/N]', 290,300,4,1,1,0xffd60606)       
    end   
  end
  
  def set_score(score)   
    @score_value = score    
  end
  
  def button_down(id)
    if id == Gosu::KbSpace then @plyr.try_to_jump end
    if id == Gosu::KbEscape then save_progress end
    if id == Gosu::KbReturn then retry_game end
    if id == Gosu::KbN then save_score end
    if id == Gosu::KbY then load_level3 end    
  end  
  
  def save_highscore(username, score)         
    #save in file
    write_entry(username,score)    
  end

  def write_entry(username,score)
    @username = username
    @score = score
    @log =  {"username" => @username, "score" => @score, "level" => 2}
    if(File.exists?("highscores.yml") == true) then
      #get all scores from file
      myfile = File.open("highscores.yml","a+")
      myfile.puts YAML.dump(@log)
      myfile.close
    end
  end
end
