"""
This module contains an opionated gateway for the capakey webservice.

.. versionadded:: 0.2.0
"""

import json
import logging

import requests
from dogpile.cache import make_region

from crabpy.gateway.exception import GatewayResourceNotFoundException
from crabpy.gateway.exception import GatewayRuntimeException

log = logging.getLogger(__name__)


def capakey_rest_gateway_request(url, headers={}, params={}):
    """
    Utility function that helps making requests to the CAPAKEY REST service.

    :param string url: URL to request.
    :param dict headers: Headers to send with the URL.
    :param dict params: Parameters to send with the URL.
    :returns: Result of the call.
    """
    try:
        res = requests.get(url, headers=headers, params=params)
        res.raise_for_status()
        return res
    except requests.ConnectionError as ce:
        raise GatewayRuntimeException(
            'Could not execute request due to connection problems:\n%s' % repr(ce),
            ce
        )
    except requests.HTTPError as he:
        raise GatewayResourceNotFoundException()
    except requests.RequestException as re:
        raise GatewayRuntimeException(
            'Could not execute request due to:\n%s' % repr(re),
            re
        )


class CapakeyRestGateway:
    """
    A REST gateway to the capakey webservice.

    .. versionadded:: 0.8.0
    """

    caches = {}

    def __init__(self, **kwargs):
        self.base_url = kwargs.get(
            'base_url',
            'https://geoservices.informatievlaanderen.be/capakey/api/v2'
        )
        self.base_headers = {
            'Accept': 'application/json'
        }
        cache_regions = ['permanent', 'long', 'short']
        for cr in cache_regions:
            self.caches[cr] = make_region(key_mangler=str)
        if 'cache_config' in kwargs:
            for cr in cache_regions:
                if ('%s.backend' % cr) in kwargs['cache_config']:
                    log.debug('Configuring %s region on CapakeyRestGateway', cr)
                    self.caches[cr].configure_from_config(
                        kwargs['cache_config'],
                        '%s.' % cr
                    )

    @staticmethod
    def _parse_centroid(center):
        """
        Parse response center from the CapakeyRestGateway to (CenterX, CenterY)
        
        :param center: response center from the CapakeyRestGateway
        :return: (CenterX, CenterY)
        """
        coordinates = json.loads(center)["coordinates"]
        return coordinates[0], coordinates[1]

    @staticmethod
    def _parse_bounding_box(bounding_box):
        """
        Parse response bounding box from the CapakeyRestGateway to (MinimumX, MinimumY, MaximumX, MaximumY)
        
        :param bounding_box: response bounding box from the CapakeyRestGateway
        :return: (MinimumX, MinimumY, MaximumX, MaximumY)
        """
        coordinates = json.loads(bounding_box)["coordinates"]
        x_coords = [x for x, y in coordinates[0]]
        y_coords = [y for x, y in coordinates[0]]
        return min(x_coords), min(y_coords), max(x_coords), max(y_coords)

    def list_gemeenten(self, sort=1):
        """
        List all `gemeenten` in Vlaanderen.

        :param integer sort: What field to sort on.
        :rtype: A :class:`list` of :class:`Gemeente`.
        """

        def creator():
            url = self.base_url + '/municipality'
            h = self.base_headers
            p = {
                'orderbyCode': sort == 1
            }
            res = capakey_rest_gateway_request(url, h, p).json()
            return [
                Gemeente(r['municipalityCode'], r['municipalityName'])
                for r in res['municipalities']
            ]

        if self.caches['permanent'].is_configured:
            key = 'list_gemeenten_rest#%s' % sort
            gemeente = self.caches['permanent'].get_or_create(key, creator)
        else: