module Ropenlayer
  module ActsAs
    
    # acts_as_map: give to the model map construiction and build facilities.
    #
    #   class Team < ActiveRecord::Base
    #     acts_as_map :default_layer => :google_streets
    #   end
    #
    # Avalaible options:
    #
    #  - :longitude, :latitude, :zoom : Default starting values for map. Can be a float (latitude, longitude) or integer (zoom) object, so values will be parsed as them are. 
    #                                   A Symbol, in this case, ropenlayer will send :symbol method to mapper instance, or a valid Proc object
    #  - :default_layer: Default layer for visualization. For avalaible layers see Ropenlayer::Openlayer::Map 
    #  - :nodes: Relations which can be pointed on the map. Relations are expected to have acts_as_localizable_on behaviour in their class
    #
    # Examples
    #
    # Build a Map with static features, just for localization
    #
    #   class Team < ActiveRecord::Base
    #     acts_as_map :default_layer => :google_streets, :latitude => 40000.23, :longitude => 54555.233, :zoom => 3
    #   end
    #
    # Build a Map with Proc calls to perform automatic localization on forms
    # 
    #     class Team < ActiveRecord
    # 
    #       has_many :offices
    #       has_one :main_office, :conditions => { :main => true }
    # 
    #       acts_as_map :default_layer => :google_streets, :longitude => :main_office_longitude, :latitude => :main_office_latitude, :zoom => :main_office_zoom
    #                   :nodes         => [ :offices ]
    # 
    #       def main_office_longitude
    #           main_office.longitude
    #       end
    # 
    #       def main_office_longitude=(value)
    #         main_office_longitude = value
    #       end
    # 
    #       def main_office_latitude
    #           main_office.latitude
    #       end
    # 
    #       def main_office_latitude=(value)
    #         main_office.latitude = value
    #       end
    # 
    #       def main_office_longitude
    #           main_office.longitude
    #       end
    # 
    #       def main_office_zoom=(value)
    #         main_office.zoom = value
    #       end
    # 
    #     end
    #
    def acts_as_map(options = {})
      
      class_eval do
      
        cattr_reader :acts_as_mapper, :ropenlayer_mapper_config, :localizable
        
        send("class_variable_set", "@@acts_as_mapper",    true)
        send("class_variable_set", "@@ropenlayer_mapper_config", options)
      
        include Ropenlayer::ActsAs::Mapper

      end
    end
    
    # acts_as_localizable_on: give to the model facilities to store and draw object in a map.
    #
    #   class Team < ActiveRecord::Base
    #     acts_as_map :default_layer => :google_streets, :nodes => [ :offices ]
    #   end
    #
    #   class Office < ActiveRecord::Base
    #     belongs_to :team
    #     acts_as_localizable_on :team
    #   end
    #
    # Avalaible options:
    #
    #  All the options can be mapped to a Proc object that will bind self or a Symbol which perform send(:symbol) method.
    #  - :name, :Name of the point. By default, Just another Element
    #  - :popup_content:Content of the popup, if set, element will render a popup in click with this xhtml content. by default, is false 
    #  - :icon_url: Icon url to show, by default, /images/ropenlayer/default_marker.png
    #  - :color: Background color, by default transparent
    #
    # Examples
    #
    # Build a Map of the team offices with custom icons
    #
    #   # on app/models/team.rb
    #   class Team < ActiveRecord::Base
    #     has_many :offices
    #     acts_as_map :default_layer => :google_streets, :latitude => 40000.23, :longitude => 54555.233, :zoom => 3
    #                 :nodes => [ :offices ]
    #   end
    #
    #   # on app/models/office.rb
    #   class Office < ActiveRecord::Base
    #     belongs_to :team
    #     acts_as_localizable_on :team, :icon_url      => Proc.new{|o| o.main ? '/images/main_office.png' : '/images/office.png' },
    #                                   :color         => Proc.new{|o| o.main ? 'red' : 'blue' },
    #                                   :popup_content => :full_description
    #
    #     def full_description
    #       %( #{ name } - #{ address } )
    #     end
    #  end
    #
    #
    # on your view, just
    #  
    #   apps/views/offices/index.html
    # 
    #   <div id="offices_for_team_map" style="width: 500px; height: 400px;"></div>
    #   <%= raw @team.ropenlayer_map(:id => 'offices_for_team_map').to_js %>
    def acts_as_localizable_on(relation, options = {})
      
      class_eval do
        
        cattr_reader   :acts_as_nodeable
        cattr_reader   :ropenlayer_node_config
        
        send("class_variable_set", "@@acts_as_nodeable",    true)
        send("class_variable_set", "@@ropenlayer_node_config", options)
        
        include Ropenlayer::ActsAs::Nodeable
      end
    end
  end
end