# frozen_string_literal: true

module Calagator
  module MappingHelper
    def map_provider
      Calagator.mapping_provider || 'stamen'
    end

    def leaflet_js
      Rails.env.production? ? ['https://cdnjs.cloudflare.com/ajax/libs/leaflet/0.7.3/leaflet.js'] : ['leaflet']
    end

    def map_provider_dependencies
      {
        'stamen' => ['http://maps.stamen.com/js/tile.stamen.js?v1.2.3'],
        'mapbox' => ['https://api.tiles.mapbox.com/mapbox.js/v1.3.1/mapbox.standalone.js'],
        'esri' => ['https://cdn-geoweb.s3.amazonaws.com/esri-leaflet/0.0.1-beta.5/esri-leaflet.js'],
        'google' => [
          "https://maps.googleapis.com/maps/api/js?key=#{Calagator.mapping_google_maps_api_key}&sensor=false",
          'leaflet_google_layer'
        ]
      }[map_provider] || []
    end

    def mapping_js_includes
      leaflet_js + map_provider_dependencies
    end

    def map(items, options = {})
      options.symbolize_keys!
      Map.new(items, self, options).render
    end

    class Map < Struct.new(:items, :context, :options)
      def render
        return if locatable_items.empty?

        args = js_args.to_json[1...-1] # "splat" arguments by removing wrapping square brackets
        map_div + context.javascript_tag("map(#{args});")
      end

      private

      def js_args
        [
          layer_constructor,
          map_tiles,
          div_id,
          center,
          zoom,
          marker_color,
          markers,
          should_fit_bounds
        ]
      end

      def map_div
        context.content_tag(:div, '', id: div_id)
      end

      def div_id
        options[:id] || 'map'
      end

      def zoom
        options[:zoom] || 14
      end

      def center
        (options[:center] || locatable_items.first.location).map(&:to_f)
      end

      def should_fit_bounds
        locatable_items.count > 1 && options[:center].blank?
      end

      def markers
        Array(locatable_items).map do |locatable_item|
          next unless location = locatable_item.location

          {
            latitude: location[0],
            longitude: location[1],
            title: locatable_item.title,
            popup: context.link_to(locatable_item.title, locatable_item)
          }
        end.compact
      end

      def marker_color
        Calagator.mapping_marker_color
      end

      def locatable_items
        @locatable_items ||= Array(items).select { |i| i.location.present? }
      end

      def layer_constructor
        constructor_map = {
          'stamen' => 'L.StamenTileLayer',
          'mapbox' => 'L.mapbox.tileLayer',
          'esri' => 'L.esri.basemapLayer',
          'google' => 'L.Google',
          'leaflet' => 'L.tileLayer'
        }
        constructor_map[context.map_provider]
      end

      def map_tiles
        Calagator.mapping_tiles || 'terrain'
      end
    end
  end
end
