# encoding: utf-8

# TODO map results of find to location object

module Adapi
  class Location < Api

    # display types. region was formerly called province, and province is still
    # supported as parameter, a synonym for region
    LOCATIONS_HIERARCHY = [ :city, :region, :country ]

    def initialize(params = {})
      params[:service_name] = :LocationCriterionService
      
      @xsi_type = 'LocationCriterion'

      super(params)
    end

    # Example:
    # Location.find(:city => 'Prague')
    # Location.find(:country => 'CZ', :city => 'Prague')
    # Location.find(:country => 'CZ', :region => 'Prague' :city => 'Prague')
    #
    # TODO add legacy aliases: :city_name, :province_code, :country_code
    # TODO move search by id into separate method
    #
    def self.find(amount = :all, params = {})
      # set amount = :first by default
      if amount.is_a?(Hash) and params.empty?
        params = amount.clone
        amount = :first
      end

      params.symbolize_keys!
      first_only = (amount.to_sym == :first)

      # in which language to retrieve locations
      params[:locale] ||= 'en'

      # support for legacy :province parameter
      if params[:province] and not params[:region]
        params[:region] = params[:province]
      end

      # if :region parameter is in old format, replace it with province name
      if params[:region] && (params[:region] =~ /^[A-Z]{2}\-\w{1,3}$/)
        province_name = ConstantData::Location::Province.find_name_by_province_code(params[:region])
        params[:region] = province_name if province_name
      end

      # if :country parameter is valid country code, replace it with country name
      if params[:country] && (params[:country].size == 2)
        country_name = ConstantData::Location::Country.find_name_by_country_code(params[:country])
        params[:country] = country_name if country_name
      end
      
      # determine by what criteria to search
      location_type, location_name = nil, nil
      LOCATIONS_HIERARCHY.each do |param_name|
        if params[param_name]
          # FIXME use correct helper instead of humanize HOTFIX
          location_type, location_name = param_name.to_s.humanize, params[param_name]
          break
        end
      end
      
      raise "Invalid params" if location_name.nil? and not params[:id]
      
      selector = {
        :fields => ['Id', 'LocationName', 'CanonicalName', 'DisplayType', 'ParentLocations', 'Reach'],
        :predicates => [
            # PS: for searching more locations at once, switch to IN operator
            # values array for EQUALS can contain only one value (sic!)
            { :field => 'LocationName', :operator => 'EQUALS', :values => [ location_name ] },
            { :field => 'Locale', :operator => 'EQUALS', :values => [ params[:locale] ] }
        ]
      }

      if params[:id]
        selector[:predicates] = [
            { :field => 'Id', :operator => 'EQUALS', :values => [ params[:id].to_i ] }
        ]
      end

      # returns array of locations. and now the fun begins    
      locations = Location.new.service.get(selector)

      if params[:id]
        return locations.first[:location] rescue nil
      end
      
      # now we have to find location with correct display_type and TODO hierarchy
      # problematic example: Prague is both city and province (region)
      
      locations.each do |entry|
        next unless entry.is_a?(Hash)

        if entry[:location][:display_type] == location_type
          return entry[:location]
        end
      end
      
      nil
    end

    # Displays location tree - location with its parents
    # 
    def self.location_tree(location = {})
      "TODO"
    end

  end
end
