module AR
  module Game

    class Option 
      attr_accessor :ids
      attr_accessor :description
      attr_accessor :usage
      attr_accessor :chosen

      def initialize
        self.ids = []
        self.description = ""
        self.usage  = usage || "Do Somethign"

        yield self
      end

      def id
        ids.first
      end 

      def action_parameter_choice_sequence action
        return action if action.performable?
        player = action.performer

        back_choice = Option.new do |o|
          o.ids = ["b", "back"] 
          o.usage = "(b)ack"
          o.description = action.parameters.first.filled? ? "(Back)" : "(Back to Actions)"
          o.chosen = Proc.new do 
            if action.parameters.first.filled? #back should clear args
              action.parameters.each {|p| p.argument = nil} 
            else #back should go back to action menu
              action = nil     
            end
          end
        end

        until action.nil? or action.performable?
          next_param = action.next_param_to_fill
          m = AR::Game::Menu.new
          m.name = next_param.prompt_text 
          begin
            objs = (next_param.filter(player) )
          rescue StandardError => e
            puts "waring sone: #{e.to_s} #{e.backtrace}"
            objs = player.known_objects
          end

          choices = objs - action.parameters.map(&:argument)
          choices.delete player
          choices.each_with_index do |c, i|
            m.options << Option.new do |o|
              id = (i+1).to_s
              o.ids = [id] 
              o.usage = id
              o.description = c.name
              o.chosen = Proc.new do 
                next_param.argument = c
              end
            end
          end
          m.options << back_choice
          m.present
        end
        action
      end

    end


    class QuitOption < Option

      def initialize
        super do |o|
          o.description = "Quit the game"
          o.ids = ["quit","exit", "q"]
          o.usage = "(q)uit"
          o.chosen = Proc.new do
            AR.put_s "Thanks for playing!"
          end
        end
      end

    end

    class HelpOption < Option 
    end 


    class LoadGameOption < Option
      #initializes a game instance from scratch
      def initialize
        super() do |o|
          o.description  = "Load a saved game"
          o.usage = "(l)oad"
          o.ids = ["load", "l"]
          o.chosen = Proc.new do 
            AR.put_s "loading a save...."
            saves_dirname  = AR.save_dir 
            Dir.mkdir saves_dirname unless Dir.exists?(saves_dirname)

            w = AR.world_class.new
            d = File.open("#{saves_dirname}/default_world_data.yml", "r").read
            d = Psych.load(d).to_hash
            d = AR.recursive_symbolize(d)
            w.load_data d

            w.trigger AR::Events::GameStartedEvent, ({world: w})
            w.start!
            true
          end
        end
      end
    end


    class NewGameOption < Option
      #initializes a game instance from scratch
      def initialize
        super() do |o|
          o.description  = "Start a new game"
          o.usage = "(n)ew"
          o.ids = ["new", "n"]
          o.chosen = Proc.new do 
            AR.put_s "Beginning a new game...."
            #This should somehow be a variable set by the user gem consumer?
            w = AR.world_class.new
            #AR::Game::Behavior.set_world w
            w.events_engine.trigger AR::Events::GameStartedEvent, ({world: w})
            w.seed_for_new!
            w.start!
            true
          end
        end
      end
    end



    class ActionChoice < Option
      attr_accessor :player
      attr_accessor :action_class

      def initialize params 
        self.player = params[:player]
        self.action_class = params[:action_class]
        self.usage = "#{params[:usage]}" 
        self.ids = params[:ids]
        self.description = "#{params[:description]} (#{action_class.ap_cost}ap)" 
        self.chosen = Proc.new do
          action_parameter_choice_sequence action_class.new(self.player)
        end
      end
    end
    
    class ReactionChoice < ActionChoice 
      attr_accessor :attacker

      def initialize params 
        super
        self.attacker = params[:attacker]
        self.chosen = Proc.new do
          action_parameter_choice_sequence action_class.new(self.player, self.attacker)
        end
      end
    end
 
    class LootChoice < ActionChoice 
      def initialize player
        super player: player,
          action_class: LootAction,
          usage: "(l)oot",
          ids: ["l", "loot"],
          description: "Loot a body or container"
      end
    end



    class RestChoice < ActionChoice 
      def initialize player
        super player: player,
          action_class: RestAction,
          usage: "(r)est",
          ids: ["r", "rest"],
          description: "Restore health, but increase hunger"
      end
    end

    class JournalChoice < ActionChoice 
      def initialize player
        super player: player,
          action_class: JournalAction,
          usage: "(j)ournal",
          ids: ["j", "journal"],
          description: "Write down your progress"
      end
    end

    class QuitChoice < ActionChoice 
      def initialize player
        super player: player,
          action_class: QuitAction,
          usage: "(q)uit",
          ids: ["q", "quit"],
          description: "Quit the game"
      end
    end



    class StatusChoice < ActionChoice 
      def initialize player
        super player: player,
          action_class: StatusAction,
          usage: "(st)atus",
          ids: ["st", "status"],
          description: "Check your current state"
      end
    end




   
    class DefendChoice < ReactionChoice
      def initialize player, attacker
        super player: player,
          attacker: attacker,
          action_class: DefendAction,
          usage: "(d)efend",
          ids: ["d", "defend"],
          description: "Mitigate the attack"
      end
    end


    class ConsumeChoice < ActionChoice 
      def initialize player
        super player: player,
              action_class: ConsumeAction,
              usage: "(c)onsume",
              ids: ["c", "consume"],
              description: "Eat or drink something"
      end
    end

    class EquipChoice < ActionChoice 
      def initialize player
        super player: player,
              action_class: EquipAction,
              usage: "(e)quip",
              ids: ["e", "equip"],
              description: "Equip an item"
      end
    end



    class UnequipChoice < ActionChoice 
      def initialize player
        super player: player,
              action_class: UnequipAction,
              usage: "(un)equip",
              ids: ["un", "unequip"],
              description: "Unequip an item"
      end
    end


    class WaitChoice < ActionChoice 
      def initialize player
        super player: player,
              action_class: WaitAction,
              usage: "(w)ait",
              ids: ["w", "wait"],
              description: "End your turn"
      end
    end

    class InspectChoice < ActionChoice 
      def initialize player
        super player: player,
              action_class: InspectAction,
              usage: "(i)nspect",
              ids: ["i", "inspect"],
              description: "Inspect something"

      end
    end

    
    class TravelChoice < ActionChoice
      def initialize player
        super player: player,
              action_class: TravelAction,
              usage: "(t)ravel",
              ids: ["t", "travel"],
              description: "Travel somewhere"

      end
    end
 



    
    class AttackChoice < ActionChoice
      def initialize player
        super player: player,
              action_class: AttackAction,
              usage: "(a)ttack",
              ids: ["a", "attack"],
              description: "Attack something"
      end
    end
  
    class GrabChoice < ActionChoice
      def initialize player
        super player: player,
              action_class: GrabAction,
              usage: "(g)rab",
              ids: ["g", "grab"],
              description: "Pick something up"
      end
    end
  

    class TalkChoice < ActionChoice
      def initialize player
        super player: player,
              action_class: TalkAction,
              usage: "(ta)lk",
              ids: ["ta", "talk"],
              description: "Talk to someone"
      end
    end


    class GiveChoice < ActionChoice
      def initialize player
        super player: player,
              action_class: GiveAction,
              usage: "(gi)ve",
              ids: ["gi", "ve"],
              description: "Give an item away"
      end
    end


    class PutChoice < ActionChoice
      def initialize player
        super player: player,
              action_class: PutAction,
              usage: "(p)ut",
              ids: ["p", "put"],
              description: "Put an item down"
      end
    end

=begin
    class QuitChoice < Option
      attr_accessor :player
      def initialize player
        self.player = player
        super() do |s|
          desc = "Back to main menu"
          s.ids =  ["q"]
          s.description = desc
          s.usage = "(q)uit" 
          s.chosen = Proc.new do
            QuitAction.new(player) 
          end
        end
      end
    end
=end

    class SaveChoice < Option
      attr_accessor :player
      def initialize player
        self.player = player 
        super() do |s|
          desc = "save your progress"
          s.ids = ["s"]
          s.description = desc
          s.usage = "(s)ave"
          s.chosen = Proc.new do 
            JournalAction.new(player)
          end
        end
      end
    end


  end
end
