class AR::Game::ARObject
  attr_accessor :id
  attr_accessor :created_at
  @@serialized_keys = {}

  def self.gen_id
    @@auto_incr_id ||= 0
    @@auto_incr_id += 1
    (0...50).map { ('a'..'z').to_a[rand(26)] }.join
  end
  
  def tag
    "#{self.class}@#{self.id}"
  end
 

  def self.attr_serializeable *args, &block
    @@serialized_keys[self] ||= {}
    args.each do |arg|
      next unless @@serialized_keys[self][arg].nil?
      @@serialized_keys[self][arg] = {} 
      @@serialized_keys[self][arg][:serialize_proc] = block
      self.class_eval("def #{arg}=(val);@#{arg} = val; end")
      self.class_eval("def #{arg};@#{arg}; end")
    end
  end

  def self.attr_serializeable_gauge *args

    pr = Proc.new do |gauge, kase|
      case kase
      when :unload
        gauge.unload_data
      when :load
        g = AR::Gauge.new
        g.load_data gauge
      end
    end
    self.send("attr_serializeable", *args, &pr)
  end


  def self.serialized_attribute_tags
    @@serialized_keys[self].map{|elem| elem[:attr_tag]}
  end

  def self.unload_data_from instance
    ret = {}
    @@serialized_keys[self] ||= {}
    @@serialized_keys[self].each do |k, v|
      process = @@serialized_keys[self][k][:serialize_proc]
      unless process.nil? 
        ret[k] = process.call(instance.send(k), :unload, instance) 
      else
        ret[k] = instance.send(k)
      end
    end
    ret
  end

  def self.unload_data params
    instance = params[:_for] || params[:ar_object]
    unload_data_from instance
  end

  def self.load_data params
    instance = params[:_for] || params[:ar_object]
    #data should == ret from unload_data
    data = params[:data]
    data.each do |serialized_key,v|
      process = @@serialized_keys[self][serialized_key.to_sym][:serialize_proc]
      if process.nil?
        instance.send("#{serialized_key}=", v)
      else
        v = process.call(v, :load, instance)
        instance.send("#{serialized_key}=",v) 
      end
    end
  end

  def unload_data
    self.class.unload_data _for: self
  end

  def load_data d
    self.class.load_data _for: self, data: d
  end

  def initialize id = nil
    @id = id || AR::Game::ARObject.gen_id
    self.created_at = Time.now
    extend AR::Game::Behavior 
  end 

end



#order matters here....
#i.e. scenes and characters are types of physical objects
require_relative "ar_object/physical_object"
require_relative "ar_object/world"
require_relative "ar_object/scene"
require_relative "ar_object/character"
require_relative "ar_object/beast"
require_relative "ar_object/npc"
require_relative "ar_object/monster"

require_relative "ar_object/door"
require_relative "ar_object/player"
require_relative "ar_object/item"
require_relative "ar_object/piece_of_equipment"
require_relative "ar_object/weapon"
require_relative "ar_object/shield"
require_relative "ar_object/body_armor"

require_relative "ar_object/printer"
require_relative "ar_object/gauge"

require_relative "ar_object/buff"

require_relative "ar_object/bed"
require_relative "ar_object/lootable_thing"
require_relative "ar_object/sm_world"
require_relative "ar_object/giant_beetle"

require_relative "ar_object/old_man"
require_relative "ar_object/mushroom_potion"
require_relative "ar_object/beetle_jerky"
require_relative "ar_object/invisible"
require_relative "ar_object/moldy_log"
require_relative "ar_object/red_mushroom"
require_relative "ar_object/beetle_corpse"
require_relative "ar_object/beetle_chitin"

require_relative "ar_object/antidote"
require_relative "ar_object/beetle_meat"
require_relative "ar_object/green_mushroom"
require_relative "ar_object/torch"
require_relative "ar_object/scroll"


require_relative "ar_object/chitin_sword"
require_relative "ar_object/chitin_dagger"
require_relative "ar_object/chitin_shield"
require_relative "ar_object/chitin_chest"

require_relative "ar_object/forest01"
require_relative "ar_object/forest01_path_north"
require_relative "ar_object/forest01_hidden_path_south"

require_relative "ar_object/forest02"
require_relative "ar_object/forest02_path_south"
require_relative "ar_object/forest02_path_north"

require_relative "ar_object/forest03"
require_relative "ar_object/forest03_path_north"
require_relative "ar_object/forest03_path_south"
require_relative "ar_object/forest03_entrance_east"

require_relative "ar_object/forest04"
require_relative "ar_object/forest04_path_north"
require_relative "ar_object/forest04_path_south"
require_relative "ar_object/forest04_path_east"

require_relative "ar_object/forest05"
require_relative "ar_object/forest05_path_west"
require_relative "ar_object/forest05_gate_to_courtyard"

require_relative "ar_object/old_man_courtyard"
require_relative "ar_object/old_man_courtyard_gate_to_forest"
require_relative "ar_object/old_man_courtyard_door_inside"

require_relative "ar_object/old_man_house"
require_relative "ar_object/old_man_house_door_outside"


require_relative "ar_object/forest06"



require_relative "ar_object/poisonous_red_shroom"
require_relative "ar_object/cave01"


require_relative "ar_object/cave01_exit_west"
require_relative "ar_object/cave01_passage_east"


require_relative "ar_object/cave02"
require_relative "ar_object/cave02_passage_east"
require_relative "ar_object/cave02_passage_west"
require_relative "ar_object/cave02_hidden_passage_south"


require_relative "ar_object/cave03"
require_relative "ar_object/cave03_passage_east"
require_relative "ar_object/cave03_passage_west"


require_relative "ar_object/cave04"
require_relative "ar_object/cave04_passage_west"
require_relative "ar_object/cave04_hidden_passage_east"

require_relative "ar_object/hidden_cave01"
require_relative "ar_object/hidden_cave01_passage_north"

require_relative "ar_object/hidden_cave02"
require_relative "ar_object/hidden_cave02_passage_west"
require_relative "ar_object/hidden_forest01"
require_relative "ar_object/hidden_forest02"
require_relative "ar_object/hidden_forest01_path_north"
require_relative "ar_object/hidden_forest02_path_south"
require_relative "ar_object/forest06_hidden_path_north"
require_relative "ar_object/forest01_hidden_path_south"

require_relative "ar_object/forest06_path_south"

require_relative "ar_object/cave_spider"
require_relative "ar_object/armor_beetle"

require_relative "ar_object/large_cave_spider"
require_relative "ar_object/cave_spider_corpse"
require_relative "ar_object/iron_dagger"
require_relative "ar_object/iron_sword"
require_relative "ar_object/skeleton"
require_relative "ar_object/maze_forest"
require_relative "ar_object/forest01_path_west"
require_relative "ar_object/plains"

require_relative "ar_object/maze_path"
require_relative "ar_object/necromancers_assistant"

require_relative "ar_object/chest"
require_relative "ar_object/iron_armor"
require_relative "ar_object/hardness_potion"