# Copyright 2016 Google Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""Interact with Stackdriver Logging via JSON-over-HTTP."""

import functools

from google.cloud import _http
from google.cloud.iterator import HTTPIterator

from google.cloud.logging import __version__
from google.cloud.logging._helpers import entry_from_resource
from google.cloud.logging.sink import Sink
from google.cloud.logging.metric import Metric


_CLIENT_INFO = _http.CLIENT_INFO_TEMPLATE.format(__version__)


class Connection(_http.JSONConnection):
    """A connection to Google Stackdriver Logging via the JSON REST API.

    :type client: :class:`~google.cloud.logging.client.Client`
    :param client: The client that owns the current connection.
    """

    API_BASE_URL = 'https://logging.googleapis.com'
    """The base of the API call URL."""

    API_VERSION = 'v2'
    """The version of the API, used in building the API call's URL."""

    API_URL_TEMPLATE = '{api_base_url}/{api_version}{path}'
    """A template for the URL of a particular API call."""

    _EXTRA_HEADERS = {
        _http.CLIENT_INFO_HEADER: _CLIENT_INFO,
    }


class _LoggingAPI(object):
    """Helper mapping logging-related APIs.

    See
    https://cloud.google.com/logging/docs/reference/v2/rest/v2/entries
    https://cloud.google.com/logging/docs/reference/v2/rest/v2/projects.logs

    :type client: :class:`~google.cloud.logging.client.Client`
    :param client: The client used to make API requests.
    """

    def __init__(self, client):
        self._client = client
        self.api_request = client._connection.api_request

    def list_entries(self, projects, filter_=None, order_by=None,
                     page_size=None, page_token=None):
        """Return a page of log entry resources.

        See
        https://cloud.google.com/logging/docs/reference/v2/rest/v2/entries/list

        :type projects: list of strings
        :param projects: project IDs to include. If not passed,
                            defaults to the project bound to the client.

        :type filter_: str
        :param filter_:
            a filter expression. See
            https://cloud.google.com/logging/docs/view/advanced_filters

        :type order_by: str
        :param order_by: One of :data:`~google.cloud.logging.ASCENDING`
                         or :data:`~google.cloud.logging.DESCENDING`.

        :type page_size: int
        :param page_size: maximum number of entries to return, If not passed,
                          defaults to a value set by the API.

        :type page_token: str
        :param page_token: opaque marker for the next "page" of entries. If not
                           passed, th
e API will return the first page of
                           entries.

        :rtype: :class:`~google.cloud.iterator.Iterator`
        :returns: Iterator of :class:`~google.cloud.logging.entries._BaseEntry`
                  accessible to the current API.
        """
        extra_params = {'projectIds': projects}

        if filter_ is not None:
            extra_params['filter'] = filter_

        if order_by is not None:
            extra_params['orderBy'] = order_by

       
 if page_size is not None:
            extra_params['pageSize'] = page_size

        path = '/entries:list'
        # We attach a mutable loggers dictionary so that as Logger
        # objects are created by entry_from_resource, they can be
        # re-used by other log entries from the same logger.
        loggers = {}
        item_to_value = functools.partial(
            _item_to_entry, loggers=loggers)
        iterator = HTTPIterator(
            client=self._client, path=path,
            item_to_value=item_to_value, items_key='entries',
            page_token=page_token, extra_params=extra_params)
        # This method uses POST to make a read-only request.
        iterator._HTTP_METHOD = 'POST'
        return iterator

    def write_entries(self, entries, logger_name=None, resource=None,
                      labels=None):
        """API call:  log an entry resource via a POST request

        See
        https://cloud.google.com/logging/docs/reference/v2/rest/v2/entries/write

        :type entries: sequence of mapping
        :param entries: the log entry resources to log.

        :type logger_name: str
        :param logger_name: name of default logger to which to log the entries;
                            individual entries may override.

        :type resource: mapping
        :param resource: default resource to associate with entries;
                         individual entries may override.

        :type labels: mapping
        :param labels: default labels to associate with entries;
                       individual entries may override.
        """
        data = {'entries': list(entries)}

        if logger_name is not None:
            data['logName'] = logger_name

        if resource is not None:
            data['resource'] = resource

        if labels is not None:
            data['labels'] = labels

        self.api_request(method='POST', path='/entries:write', data=data)

    def logger_delete(self, project, logger_name):
        """API call:  delete all entries in a logger via a DELETE request

        See
        https://cloud.google.com/logging/docs/reference/v2/rest/v2/projects.logs/delete

        :type project: str
        :param project: ID of project containing the log entries to delete

        :type logger_name: str
        :param logger_name: name of logger containing the log entries to delete
        """
        path = '/projects/%s/logs/%s' % (project, logger_name)
        self.api_request(method='DELETE', path=path)


class _SinksAPI(object):
    """Helper mapping sink-related APIs.

    See
    https://cloud.google.com/logging/docs/reference/v2/rest/v2/projects.sinks

    :type client: :class:`~google.cloud.logging.client.Client`
    :param client: The client used to make API requests.
    """
    def __init__(self, client):
        self._client = client
        self.api_request = client._connection.api_request

    def list_sinks(self, project, page_size=None, page_token=None):
        """List sinks for the project associated with this client.

        See
        https://cloud.google.com/logging/docs/reference/v2/rest/v2/projects.sinks/list

        :type project: str
        :param project: ID of the project whose sinks are to be listed.

        :type page_size: int
        :param page_size: maximum number of sinks to return, If not passed,
                          defaults to a value set by the API.

        :type page_token: str
        :param page_token: opaque marker for the next "page" of sinks. If not
                           passed, the API will return the first page of
                           sinks.

        :rtype: :class:`~google.cloud.iterator.Iterator`
        :returns: Iterator of
                  :class:`~google.cloud.logging.sink.Sink`
                  accessible to the current API.
        """
        extra_params = {}

        if page_size is not None:
            extra_params['pageSize'] = page_size

        path = '/projects/%s/sinks' % (project,)
        return HTTPIterator(
            client=self._client, path=path,
            item_to_value=_item_to_sink, items_key='sinks',
            page_token=page_token, extra_params=extra_params)

    def sink_create(self, project, sink_name, filter_, destination):
        """API call:  create a sink resource.

        See
        https://cloud.google.com/logging/docs/reference/v2/rest/v2/projects.sinks/create

        :type project: str
        :param project: ID of the project in which t