class Inventory
  SELECTION_CHANGED_SFX_KEY = :selection_changed_sfx

  
  def initialize(args)

    @inventory = [
      [
        Item.new("sprites/square/red.png", 1, "item_name1", "Item Name", {x: 8, y: 16}, {w: 32, h: 32}),
        Item.new("sprites/square/green.png", 1, "item_name2", "Item Name", {x: 8, y: 48}, {w: 32, h: 32}),
        Item.new("sprites/square/blue.png", 1, "item_name3", "Item Name", {x: 8, y: 80}, {w: 32, h: 32}),
        Item.new("sprites/square/yellow.png", 1, "item_name4", "Item Name", {x: 8, y: 112}, {w: 32, h: 32}),
        Item.new("sprites/square/gray.png", 1, "item_name5", "Item Name", {x: 8, y: 144}, {w: 32, h: 32})
      ],
      [
        Item.new("sprites/square/red.png", 1, "item_name1", "Item Name", {x: 104, y: 16}, {w: 32, h: 32}),
        Item.new("sprites/square/green.png", 1, "item_name2", "Item Name", {x: 104, y: 48}, {w: 32, h: 32}),
        Item.new("sprites/square/blue.png", 1, "item_name3", "Item Name", {x: 104, y: 80}, {w: 32, h: 32}),
        Item.new("sprites/square/yellow.png", 1, "item_name4", "Item Name", {x: 104, y: 112}, {w: 32, h: 32}),
        Item.new("sprites/square/gray.png", 1, "item_name5", "Item Name", {x: 104, y: 144}, {w: 32, h: 32})
      ],
      [
        Item.new("sprites/square/red.png", 1, "item_name1", "Item Name", {x: 56, y: 16}, {w: 32, h: 32}),
        Item.new("sprites/square/green.png", 1, "item_name2", "Item Name", {x: 56, y: 48}, {w: 32, h: 32}),
        Item.new("sprites/square/blue.png", 1, "item_name3", "Item Name", {x: 56, y: 80}, {w: 32, h: 32}),
        Item.new("sprites/square/yellow.png", 1, "item_name4", "Item Name", {x: 56, y: 112}, {w: 32, h: 32}),
        Item.new("sprites/square/gray.png", 1, "item_name5", "Item Name", {x: 56, y: 144}, {w: 32, h: 32})
      ]
    ]

    @selected_position = {x: 0, y: 0}

    @display = false
    @display_state = :closed

    @position = {x: -352, y: 48}
    @size = {w: 352, h: 256}
    @speed = {x: 16, y: 0}

    @selection_frame = 0
    @selection_frame_delay = 5

    @last_input_time = 0

    @item_selection_sfx = {input: "sounds/vgmenuselect5.wav"}

    @selected_item =  @inventory[@selected_position.x][@selected_position.y]

    _setup_inventory_rt(args)
  end

  def tick(args)
    return if @display_state == :closed

    case @display_state
    when :closed
      if @display
        @display_state = :opening
      end
    when :opening
      if @position.x < 0
        @position.x += @speed.x
      elsif @position.x >= 0
        @display_state = :open
        @position.x = 0
      end
    when :closing
      if @position.x > -352
        @position.x -= @speed.x
      elsif @position.x <= -352
        @display_state = :closed
        @position.x = -352
      end
    when :open
      if !@display
        @display_state = :closing
      end
    end

    _process_input(args)
    selection_frame_delay = 8
    if args.state.tick_count % selection_frame_delay == 0
      @selection_frame += 1
      @selection_frame = @selection_frame % 2
    end

    draw(args)
  end

  def toggle_display
    @display ^= true
    @display_state = :opening
  end

  def draw(args)
    rt_name = :inventory
  
    _setup_inventory_rt(args)
  
    @inventory_rt.solids << {x: 0, y: 0, **@size, **Color::BLACK}
    @inventory_rt.borders << {x: 0, y: 0, **@size, **Color::WHITE}
    
    sel_pos = {x: 6 + (@selected_position.x * 48), y: 14 + (@selected_position.y * 32)}
    @inventory_rt.primitives << render()
    @inventory_rt.primitives << {
      **sel_pos, w: 36, h: 36,
      source_x: (@selection_frame * 48), source_y: 0, source_w: 48, source_h: 48,
      path: "sprites/ui/selection_indicator.png", primitive_marker: :sprite
    }
  
    buffer_rt = args.outputs[:buffer]
    buffer_rt.primitives << {**@position, **@size, path: rt_name, primitive_marker: :sprite}
  end

  def render
    @inventory.flatten.compact.map(&:to_h)
  end

  def is_closed?
    @display_state == :closed
  end

  def is_open?
    @display_state == :open || @display_state == :closing || @display_state == :opening
  end

  def item_at(x, y)
    @inventory[x][y]
  end

  def selected_item
    item_at(@selected_position.x, @selected_position.y)
  end

  private

  def _setup_inventory_rt(args)
    @inventory_rt = args.outputs[:inventory]
    @inventory_rt.w = @size.w
    @inventory_rt.h = @size.h
  end

  def _process_input(args)
    #make sure the selection sfx is done playing before we move the selection again
    return if args.audio[SELECTION_CHANGED_SFX_KEY] && args.audio[SELECTION_CHANGED_SFX_KEY].paused

    selection_changed = _try_move(+1, 0) if args.inputs.keyboard.key_down.right
    selection_changed = _try_move(-1, 0) if args.inputs.keyboard.key_down.left
    selection_changed = _try_move(0, -1) if args.inputs.keyboard.key_down.down
    selection_changed = _try_move(0, +1) if args.inputs.keyboard.key_down.up

    args.audio[SELECTION_CHANGED_SFX_KEY] = @item_selection_sfx if selection_changed
  end

  def _try_move(x_offset, y_offset)
    x = @selected_position.x + x_offset
    y = @selected_position.y + y_offset
    
    # can't move past the edges
    if !x_offset.zero?
      return false if x < 0
      return false if x >= @inventory.count
    end
    if !y_offset.zero?
      return false if y < 0
      return false if y >= @inventory[@selected_position.x].count
    end
    
    potential_item = item_at(x, y)
    if potential_item
      @selected_position = {x: x, y: y}
      
      true
    else
      false
    end
  end
end