include StarRuby

module FallingBlocks
  
  class View
    
    def render_text(screen, text, x, y, in_window = false)
      fore_color = in_window ? Color.new(255, 255, 255) : Color.new(51, 51, 153)
      screen.render_text(text, x + 1, y + 8 + 1, @font, Color.new(0, 0, 0, 64))
      screen.render_text(text, x, y + 8, @font, fore_color)
    end
    
    private :render_text
    
    def render_piece(screen, piece, x, y, angle = 0, options = {})
      blocks = @textures[:blocks]
      piece.height.times do |j|
        piece.width.times do |i|
          if piece[i, j, angle]
            screen.render_texture(blocks, x + i * 10, y + j * 10, {
              :src_x => piece.id * 10, :src_width => 10, :src_height => 10
            }.merge(options))
          end
        end
      end
    end
    
    private :render_piece

    attr_reader :model
    
    def initialize(model)
      @model = model
      @textures = {
        :background        => Texture.load("images/falling_blocks/background"),
        :blocks            => Texture.load("images/falling_blocks/blocks"),
        :field_window      => Texture.new(100, 200),
        :next_piece_window => Texture.new(50, 50),
        :score_window      => Texture.new(140, 20),
        :level_window      => Texture.new(140, 20),
        :lines_window      => Texture.new(140, 20),
        :start_info        => Texture.new(320, 240),
        :pause_info        => Texture.new(320, 240),
        :gameover_info     => Texture.new(320, 240),
      }
      @font = Font.new("fonts/falling_blocks/flappy_for_famicom", 8)
      
      texture = @textures[:start_info]
      texture.fill(Color.new(0, 0, 0, 128))
      str = "PRESS ANY KEY TO PLAY"
      width, height = @font.get_size(str)
      render_text(texture, str, (texture.width - width) / 2, (texture.height - height) / 2, true)
      
      texture = @textures[:pause_info]
      texture.fill(Color.new(0, 0, 0, 128))
      str = "PAUSE"
      width, height = @font.get_size(str)
      render_text(texture, str, (texture.width - width) / 2, (texture.height - height) / 2, true)
      
      texture = @textures[:gameover_info]
      texture.fill(Color.new(0, 0, 0, 128))
      str = "GAME OVER"
      width, height = @font.get_size(str)
      render_text(texture, str, (texture.width - width) / 2, (texture.height - height) / 2, true)
    end
    
    def update(screen)
      # clear windows
      @textures.keys.select{|k| k.to_s =~ /window$/}.each do |key|
        @textures[key].fill(Color.new(0, 0, 0, 192))
      end
      
      # render the field
      if [:playing, :gameover].include?(model.state)
      window = @textures[:field_window]
        blocks = @textures[:blocks]
        field = model.field
        field.height.times do |j|
          field.width.times do |i|
            if field[i, j]
              window.render_texture(blocks, i * 10, j * 10, {
                :src_x => field[i, j] * 10, :src_width => 10, :src_height => 10
              })
            end
          end
        end
      end
      
      # render the falling piece
      if [:playing, :gameover].include?(model.state)
        window = @textures[:field_window]
        x = model.falling_piece_x
        y = model.falling_piece_y
        angle = model.falling_piece_angle
        options = {}
        options.merge!({
          :tone_red => 128, :tone_green => 128, :tone_blue => 128
        }) if model.falling_piece_landing?
        render_piece(window, model.falling_piece, x * 10, y * 10, angle, options)
      end
      
      # render flashing
      if model.state == :playing and model.flashing?
        window = @textures[:field_window]
        lines = model.field.flashing_lines
        flashing_texture = Texture.new(model.field.width * 10, 10)
        flashing_texture.fill(Color.new(255, 0, 0, 128))
        lines.each do |line|
          window.render_texture(flashing_texture, 0, line * 10)
        end
      end
      
      # render the next piece
      if [:playing, :gameover].include?(model.state) and model.next_piece
        window = @textures[:next_piece_window]
        x = (window.width - model.next_piece.width * 10) / 2
        y = (window.height - model.next_piece.height * 10) / 2
        render_piece(window, model.next_piece, x, y)
      end
      
      # render texts
      %w(score level lines).each do |key|
        value = model.send(key).to_s
        texture = @textures["#{key}_window".intern]
        x = texture.width - @font.get_size(value)[0] - 5
        render_text(texture, value, x, 0, true)
      end
      
      screen.clear
      
      screen.render_texture(@textures[:background], 0, 0)
      screen.render_texture(@textures[:field_window], 20, 20)
      
      render_text(screen, "NEXT", 140, 15)
      screen.render_texture(@textures[:next_piece_window], 140, 35)
      render_text(screen, "SCORE", 140, 100)
      screen.render_texture(@textures[:score_window], 140, 120)
      render_text(screen, "LEVEL", 140, 140)
      screen.render_texture(@textures[:level_window], 140, 160)
      render_text(screen, "LINES", 140, 180)
      screen.render_texture(@textures[:lines_window], 140, 200)
      
      case model.state
      when :start
        screen.render_texture(@textures[:start_info], 0, 0)
      when :pause
        screen.render_texture(@textures[:pause_info], 0, 0)
      when :gameover
        screen.render_texture(@textures[:gameover_info], 0, 0)
      end
    end
    
  end
  
end
