# frozen_string_literal: true module JDX module Geocoder class Google include Base RADIUS = 6371 CITY_FIELDS = %w[locality sublocality administrative_area_level_2 administrative_area_level_3].freeze def initialize(term) @term = term end # coordinate order is longitude, latitude def coordinates data.dig('geometry', 'location').values.reverse! end def latitude data.dig('geometry', 'location', 'lat') end def longitude data.dig('geometry', 'location', 'lng') end def address data['formatted_address'] end def city CITY_FIELDS.each do |c| if (r = type_find(c, 'long_name')) return r end end nil end def state type_find('administrative_area_level_1', 'long_name') end def country type_find('country', 'long_name') end def state_code type_find('administrative_area_level_1', 'short_name') end def country_code type_find('country', 'short_name') end def postal_code type_find('postal_code', 'short_name') end # [[northeast] [southwest]] def bounds @bounds ||= begin bounds = data.dig('geometry', 'bounds') || data.dig('geometry', 'viewport') return nil if bounds.nil? bounds.values.map do |v| v.values.reverse! end end end def center @center ||= begin co1, co2 = bounds [(co1[0] + co2[0]) / 2, (co1[1] + co2[1]) / 2] end end def spherical_distance # rubocop:disable Metrics/AbcSize rlng1, rlat1 = deg2rad(*bounds[1]) rlng2, rlat2 = deg2rad(*center) (2 * RADIUS * Math.asin(Math.sqrt(Math.sin((rlat2 - rlat1) / 2)**2 + Math.cos(rlat1) * Math.cos(rlat2) * Math.sin((rlng2 - rlng1) / 2)**2))).round(3) end def deg2rad(lng, lat) [lng * Math::PI / 180, lat * Math::PI / 180] end def types data['types'] end def place_id data['place_id'] end private def type_find(area, range) data['address_components'].find { |a| a['types'].include?(area) }&.dig(range) end def url "https://maps.googleapis.com/maps/api/geocode/json?key=#{google_key}&address=#{escape_term}®ion=us" end def serialize_data(response_data) response_data['results'][0] end def handle_response response = typhoeus_get if response.success? data = parse_json(response.body) return [true, data] end handle_request_error(response) false end def google_key @google_key ||= Geocoder.configuration.google_key end def cache_redis @cache_redis ||= Geocoder.configuration.location_cache_db end end end end