# =============================================================================
# Copyright (c) 2018 Tom Kralidis
#
# Authors : Tom Kralidis <tomkralidis@gmail.com>
#
# Contact email: tomkralidis@gmail.com
# =============================================================================

import json
import logging

from six.moves.urllib.parse import urljoin
import requests

from owslib import __version__

LOGGER = logging.getLogger(__name__)

REQUEST_HEADERS = {
    'User-Agent': 'OWSLib {} (https://geopython.github.io/OWSLib)'.format(
        __version__)
}


class WebFeatureService_3_0_0(object):
    """Abstraction for OGC Web Feature Service (WFS) version 3.0"""
    def __init__(self, url, version, json_, timeout=30, username=None,
                 password=None):
        """
        initializer; implements Requirement 1 (/req/core/root-op)

        @type url: string
        @param url: url of WFS root document
        @type json_: string
        @param json_: json object
        @param timeout: time (in seconds) after which requests should timeout
        @param username: service authentication username
        @param password: service authentication password

        @return: initialized WebFeatureService_3_0_0 object
        """

        if '?' in url:
            self.url, self.url_query_string = url.split('?')
        else:
            self.url = url.rstrip('/') + '/'
            self.url_query_string = None

        self.version = version
        self.json_ = json_
        self.timeout = timeout
        self.username = username
        self.password = password

        if json_ is not None:  # static JSON string
            self.links = json.loads(json_)['links']
        else:
            response = requests.get(url, headers=REQUEST_HEADERS).json()
            self.links = response['links']

    def conformance(self):
        """
        implements Requirement 5 (/req/core/conformance-op)

        @returns: conformance object
        """

        url = self._build_url('conformance')
        LOGGER.debug('Request: {}'.format(url))
        response = requests.get(url, headers=REQUEST_HEADERS).json()
        return response

    def collections(self):
        """
        implements Requirement 9 (/req/core/collections-op)

        @returns: collections object
        """

        url = self._build_url('collections')
        LOGGER.debug('Request: {}'.format(url))
        response = requests.get(url, headers=REQUEST_HEADERS).json()
        return response['collections']

    def collection(self, collection_name):
        """
        implements Requirement 15 (/req/core/sfc-md-op)

        @type collection_name: string
        @param collection_name: name of collection

        @returns: feature collection metadata
        """

        path = 'collections/{}'.format(collection_name)
        url = self._build_url(path)
        LOGGER.debug('Request: {}'.format(url))
        response = requests.get(url, headers=REQUEST_HEADERS).json()
        return response

    def collection_items(self, collection_name, **kwargs):
        """
        implements Requirement 17 (/req/core/fc-op)

        @type collection_name: string
        @param collection_name: name of collection
        @type bbox: list
        @param bbox: list of minx,miny,maxx,maxy
        @type time: string
        @param time: time extent or time instant
        @type limit: int
        @param limit: limit number of features
        @type startindex: int
        @param startindex: start position of results

        @returns: feature results
        """

        if 'bbox' in kwargs:
            kwargs['bbox'] = ','.join(kwargs['bbox'])

        path = 'collections/{}/items'.format(collection_name)
        url = self._build_url(path)
        LOGGER.debug('Request: {}'.format(url))
        response = requests.get(url, headers=REQUEST_HEADERS,
                                params=kwargs).json()
        return response

    def collection_item(self, collection_name, identifier):
        """
        implements Requirement 30 (/req/core/f-op)

        @type collection_name: string
        @param collection_name: name of collection
        @type identifier: string
        @param identifier: feature identifier

        @returns: single feature result
        """

        path = 'collections/{}/items/{}'.format(collection_name, identifier)
        url = self._build_url(path)
        LOGGER.debug('Request: {}'.format(url))
        response = requests.get(url, headers=REQUEST_HEADERS).json()
        return response

    def _build_url(self, path=None):
        """
        helper function to build a WFS 3.0 URL

        @type path: string
        @param path: path of WFS URL

        @returns: fully constructed URL path
        """

        url = self.url
        if self.url_query_string is not None:
            LOGGER.debug('base URL has a query string')
            url = urljoin(url, path)
            url = '?'.join([url, self.url_query_string])
        else:
            url = urljoin(url, path)

        LOGGER.debug('URL: {}'.format(url))
        return url
