module Ropenlayer
  module Openlayer
    class Feature
      
      DEFAULT_ICON_SIZE = [ 40, 34 ]
      DEFAULT_ICON_URL  = "/images/ropenlayer/default_marker.png"
      
      attr_reader :map
      
      def self.draw_collection(map_object)
        features = map_object.draw_features
        feature_objects = features.inject([]) do |objects, feature_data|
          objects << new(map_object, feature_data)
          objects
        end
        %( //Adding features
           #{ feature_objects.map(&:to_js) } )
      end
      
      def initialize(map, attributes)
        @map           = map
        @id            = attributes[:id]            || raise("No defined id for feature #{ attributes.inspect }")      
        @js_id         = "#{ @map.js_id }node#{ @id }"
        @name          = attributes[:name]          || 'Another Feature'
        @popup_content = attributes[:popup_content] || false
        @geometry      = attributes[:geometry]      || raise("No defined geometry for feature #{ attributes.inspect }")
        @longitude     = attributes[:longitude]     || raise("No defined longitude for feature #{ attributes.inspect }")
        @latitude      = attributes[:latitude]      || raise("No defined latitude for feature #{ attributes.inspect }")
        @icon_url      = attributes[:icon_url]
        @icon_size     = attributes[:icon_size]
        @color         = attributes[:color]
        @localizations = attributes[:localizations]
      end
      
      def to_js
        %( #{ build_main_geometry  }
           #{ build_vector_feature }
           #{ build_main_icon      }
           #{ build_main_feature   }
           
           #{ build_marker_click_function if @popup_content }
           
           #{  Ropenlayer::Openlayer::Js.new("#{ @map.markers_layer.js_id }.addMarker(#{  @js_id }MainMarker)").to_js } 
           #{  Ropenlayer::Openlayer::Js.new("#{ @map.vectors_layer.js_id }.addFeatures([#{  @js_id }VectorFeature, #{  @js_id }MainFeature])").to_js } 
           
           
        )
        
      end

      private
      def build_main_geometry
        case @geometry
        when "POINT"
          return Ropenlayer::Openlayer::Js.new_var("#{ @js_id }MainGeometry", Ropenlayer::Openlayer::Js.new_method("OpenLayers.Geometry.Point", :args => [ @longitude, @latitude ]).to_s).to_js
        when "LINESTRING"
          return %(  #{ Ropenlayer::Openlayer::Js.new_var("#{ @js_id }LinearPoints", "[]").to_js }
                     #{ @localizations.inject('') do |points_in_line, localization|
                          point_in_line  =  Ropenlayer::Openlayer::Js.new_method("OpenLayers.Geometry.Point", :args => [ localization[:longitude], localization[:latitude] ]).to_s
                          points_in_line << Ropenlayer::Openlayer::Js.new("#{ @js_id }LinearPoints.push(#{ point_in_line }) ").to_js
                          points_in_line
                        end }
                      #{ Ropenlayer::Openlayer::Js.new_var("#{ @js_id }MainGeometry", Ropenlayer::Openlayer::Js.new_method("OpenLayers.Geometry.LineString", :args => ["#{ @js_id }LinearPoints"]).to_s).to_js } )
        when "POLYGON"
          return %(  #{ Ropenlayer::Openlayer::Js.new_var("#{ @js_id }LinearPoints", "[]").to_js }
                     #{ @localizations.inject('') do |points_in_line, localization|
                          point_in_line  =  Ropenlayer::Openlayer::Js.new_method("OpenLayers.Geometry.Point", :args => [ localization[:longitude], localization[:latitude] ]).to_s
                          points_in_line << Ropenlayer::Openlayer::Js.new("#{ @js_id }LinearPoints.push(#{ point_in_line }) ").to_js
                          points_in_line
                        end }
                      #{ Ropenlayer::Openlayer::Js.new_var("#{ @js_id }LinearRing",  Ropenlayer::Openlayer::Js.new_method("OpenLayers.Geometry.LinearRing", :args => ["#{ @js_id }LinearPoints"]).to_s).to_js }
                      #{ Ropenlayer::Openlayer::Js.new_var("#{ @js_id }MainGeometry", Ropenlayer::Openlayer::Js.new_method("OpenLayers.Geometry.Polygon", :args => ["#{ @js_id }LinearRing"]).to_s).to_js } )
        end
      end
      
      def build_vector_feature
        vector_feature_method = Ropenlayer::Openlayer::Js.new_method("OpenLayers.Feature.Vector", :args => [ "#{ @js_id }MainGeometry" ]).to_s
        %( #{ Ropenlayer::Openlayer::Js.new_var("#{ @js_id }VectorFeature", vector_feature_method).to_js }
           #{ Ropenlayer::Openlayer::Js.new("#{ @js_id }VectorFeature.attributes = { name: '#{ @name }', favColor: 'red', fillColor: '#{ @color }' }").to_js } )
      end
        
      def build_main_icon
        icon_size   = (@icon_size and @icon_size.is_a?(Array)) ? @icon_size : DEFAULT_ICON_SIZE
        icon_url    = (@icon_url  and @icon_url.is_a?(String)) ? @icon_url  : DEFAULT_ICON_URL

        size_method   = Ropenlayer::Openlayer::Js.new_method("OpenLayers.Size", :args => icon_size).to_s
        offset_method = Ropenlayer::Openlayer::Js.new("function(size){ return new OpenLayers.Pixel(-(size.w/2), -(size.h/2)) }").to_s
        
        icon_method   = Ropenlayer::Openlayer::Js.new_method("OpenLayers.Icon", :args => [ "'#{ icon_url }'", size_method, 'null', offset_method ]).to_s
        %( #{ Ropenlayer::Openlayer::Js.new_var("#{ @js_id }Icon", icon_method).to_js } )
      end

      def build_main_feature
        main_feature_lonlat = Ropenlayer::Openlayer::Js.new_method("OpenLayers.LonLat", :args => [ @longitude, @latitude ]).to_s
        main_feature_method = Ropenlayer::Openlayer::Js.new_method("OpenLayers.Feature", :args => [ @map.vectors_layer.js_id, main_feature_lonlat ]).to_s
        %( #{ Ropenlayer::Openlayer::Js.new_var("#{ @js_id }MainFeature", main_feature_method).to_js }
           #{ Ropenlayer::Openlayer::Js.new("#{ @js_id }MainFeature.data.icon = #{ @js_id }Icon").to_js }
           #{ Ropenlayer::Openlayer::Js.new_var("#{ @js_id }MainMarker", "#{ @js_id }MainFeature.createMarker()").to_js } )
      end
      
      def build_marker_click_function
        function_content = %( 
          if (this.popup == null) {
            this.popup = this.createPopup(true);
            this.popup.setBackgroundColor('#16b87d');
            this.popup.setContentHTML('#{ @popup_content }');
            #{ @map.js_id }.addPopup(this.popup);
            this.popup.show();
          } else {
            this.popup.toggle();
          }
          OpenLayers.Event.stop(evt);
        )
        %( #{ Ropenlayer::Openlayer::Js.new_var("#{ @js_id}MarkerClickFunction", "function(event) {#{ function_content }}").to_js }
           #{ Ropenlayer::Openlayer::Js.new("#{  @js_id }MainMarker.events.register('mousedown', #{ @js_id }MainFeature, #{ @js_id}MarkerClickFunction)").to_js } )
      end
    end
  end
end