text: """
  Google Geocoder service
  """
  import json
  import logging
  
  import requests
  from django.conf import settings
  
  from . import Geocoder
  
  GEOCODER_GOOGLE_URL = 'https://maps.googleapis.com/maps/api'
  
  
  class GoogleGeocoder(Geocoder):
      """
      Google geocoder class
      search and reverse from Google
      """
      coder_type = 'google'
      key = None
  
      def __new__(cls, *args, **kwargs):
          """
          Initialize
          """
          return super(Geocoder, cls).__new__(cls)
  
      def __init__(self, key: str = None, *args, **kwargs):
          """
          Google geocode engine
          Init: Geocoder('google', 'API key')
          """
          try:
              if not key and not settings.GEOCODER_GOOGLE_KEY:
                  raise ValueError(
                      "This geocoder needs an API key, please provide a key"
                      " or set GEOCODER_GOOGLE_KEY in configuration")
          except AttributeError:
              raise ValueError(
                  "This geocoder needs an API key, please provide a key "
                  "or set GEOCODER_GOOGLE_KEY in configuration")
          self.key = key or settings.GEOCODER_GOOGLE_KEY
  
      def search(self, address: str, language: str = None, bounds=None,
                 region: str = None, components: str = "") -> dict:
          """
          Google geocoding search
          Retrieves coordinates based on address
          """
          try:
              response = requests.get('{}/{}'.format(
                  GEOCODER_GOOGLE_URL,
                  'geocode/json'
              ), {
                  'address': address,
                  'key': self.key,
                  'language': language
              })
              data = response.json()
              if data.get('status') != "OK":
                  return {}
              return data
          except json.JSONDecodeError as e:
              logging.error("Invalid response")
              logging.error(e)
          except ValueError as e:
              logging.error("Invalid API configuration")
              logging.error(e)
          except IOError as e:
              logging.error("Invalid request")
              logging.error(e)
          return {}
  
      def reverse(self, lat: str, lng: str) -> dict:
          """
          Google geocoding reverse
          :param lat: latitude
          :param lng: longitude
          """
          try:
              response = requests.get('{}/{}'.format(
                  GEOCODER_GOOGLE_URL,
                  'geocode/json'
              ),
                  {
                      'latlng': ",".join(map(str, [lat, lng])),
                      'key': self.key,
                  })
              data = response.json()
              if data.get('status') != "OK":
                  return {}
              return data
          except json.JSONDecodeError as e:
              logging.error("Invalid response")
              logging.error(e)
          except ValueError as e:
              logging.error("Invalid API configuration")
              logging.error(e)
          except IOError as e:
              logging.error("Invalid request")
              logging.error(e)
          return {}
  
      def parse_countries(self, data: dict) -> [str]:
          """
          parse response from google service
          :params data: geocoding / reverse geocoding json
          :return: array of alpha2 codes
          """
          alphas = []
          if not data:
              return alphas
          for feature in data.get('results'):
              for address_component in feature.get('address_components'):
                  if 'country' in address_component.get('types'):
                      alphas.append(address_component.get('short_name'))
          return alphas
  