# Copyright 2013 NTT Corporation
#
#    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.

import re

import six
from testtools import helpers


class ExistsAllResponseHeaders(object):
    """Specific matcher to check the existence of Swift's response headers

    This matcher checks the existence of common headers for each HTTP method
    or the target, which means account, container or object.
    When checking the existence of 'specific' headers such as
    X-Account-Meta-* or X-Object-Manifest for example, those headers must be
    checked in each test code.
    """

    def __init__(self, target, method, policies=None):
        """Initialization of ExistsAllResponseHeaders

        param: target Account/Container/Object
        param: method PUT/GET/HEAD/DELETE/COPY/POST
        """
        self.target = target
        self.method = method
        self.policies = policies or []

    def _content_length_required(self, resp):
        # Verify whether given HTTP response must contain content-length.
        # Take into account the exceptions defined in RFC 7230.
        if resp.status in range(100, 200) or resp.status == 204:
            return False

        return True

    def match(self, actual):
        """Check headers

        param: actual HTTP response object containing headers and status
        """
        # Check common headers for all HTTP methods.
        #
        # Please note that for 1xx and 204 responses Content-Length presence
        # is not checked intensionally. According to RFC 7230 a server MUST
        # NOT send the header in such responses. Thus, clients should not
        # depend on this header. However, the standard does not require them
        # to validate the server's behavior. We leverage that to not refuse
        # any implementation violating it like Swift [1] or some versions of
        # Ceph RadosGW [2].
        # [1] https://bugs.launchpad.net/swift/+bug/1537811
        # [2] http://tracker.ceph.com/issues/13582
        if ('content-length' not in actual and
                self._content_length_required(actual)):
            return NonExistentHeader('content-length')
        if 'content-type' not in actual:
            return NonExistentHeader('content-type')
        if 'x-trans-id' not in actual:
            return NonExistentHeader('x-trans-id')
        if 'date' not in actual:
            return NonExistentHeader('date')

        # Check headers for a specific method or target
        if self.method == 'GET' or self.method == 'HEAD':
            if 'x-timestamp' not in actual:
                return NonExistentHeader('x-timestamp')
            if 'accept-ranges' not in actual:
                return NonExistentHeader('accept-ranges')
            if self.target == 'Account':
                if 'x-account-bytes-used' not in actual:
                    return NonExistentHeader('x-account-bytes-used')
                if 'x-account-container-count' not in actual:
                    return NonExistentHeader('x-account-container-count')
                if 'x-account-object-count' not in actual:
                    return NonExistentHeader('x-account-object-count')
                if actual['x-account-container-count'] > 0:
                    acct_header = "x-account-storage-policy-"
                    matched_policy_count = 0

                    # Loop through the policies and look for account
                    # usage data.  There should be at least 1 set
                    for policy in self.policies:
                        front_header = acct_header + policy['name'].lower()

                        usage_policies = [
                            front_header + '-bytes-used',
                            front_header + '-object-count',
                            front_header + '-container-count'
                        ]

                        # There should be 3 usage values for a give storage
                        # policy in an account bytes, object count, and
                        # container count
                        policy_hdrs = sum(1 for use_hdr in usage_policies
                                          if use_hdr in actual)

                        # If there are less than 3 headers here then 1 is
                        # missing, let's figure out which one and report
                        if policy_hdrs == 3:
                            matched_policy_count = matched_policy_count + 1
                        else:
                            if policy_hdrs > 0 and policy_hdrs < 3:
                                for use_hdr in usage_policies:
                                    if use_hdr not in actual:
                                        return NonExistentHeader(use_hdr)

                    # Only flag an error if actual policies have been read and
                    # no usage has been found
                    if self.policies and matched_policy_count == 0:
                        return GenericError("No storage policy usage headers")

            elif self.target == 'Container':
                if 'x-container-bytes-used' not in actual:
                    return NonExistentHeader('x-container-bytes-used')
                if 'x-container-object-count' not in actual:
                    return NonExistentHeader('x-container-object-count')
                if 'x-storage-policy' not in actual:
                    return NonExistentHeader('x-storage-policy')
                else:
                    policy_name = actual['x-storage-policy']

                    # loop through the policies and ensure that
                    # the value in the container header matches
                    # one of the storage policies
                    for policy in self.policies:
                        if policy['name'] == policy_name:
                            break
                    else:
                        # Ensure that there are actual policies stored
                        if self.policies:
                            return InvalidHeaderValue('x-storage-policy',
                                                      policy_name)
            elif self.target == 'Object':
                if 'etag' not in actual:
                    return NonExistentHeader('etag')
                if 'last-modified' not in actual:
                    return NonExistentHeader('last-modified')
        elif self.method == 'PUT':
            if self.target == 'Object':
                if 'etag' not in actual:
                    return NonExistentHeader('etag')
                if 'last-modified' not in actual:
                    return NonExistentHeader('last-modified')
        elif self.method == 'COPY':
            if self.target == 'Object':
                if 'etag' not in actual:
                    return NonExistentHeader('etag')
                if 'last-modified' not in actual:
                    return NonExistentHeader('last-modified')
                if 'x-copied-from' not in actual:
                    return NonExistentHeader('x-copied-from')
                if 'x-copied-from-last-modified' not in actual:
                    return NonExistentHeader('x-copied-from-last-modified')

        return None


class GenericError(object):
    """Informs an error message of a generic error during header evaluation"""

    def __init__(self, body):
        self.body = body

    def describe(self):
        return "%s" % self.body

    def get_details(self):
        return {}


class NonExistentHeader(object):
    """Informs an error message in the case of missing a certain header"""

    def __init__(self, header):
        self.header = header

    def describe(self):
        return "%s header does not exist" % self.header

    def get_details(self):
        return {}


class InvalidHeaderValue(object):
    """Informs an error message when a header contains a bad value"""

    def __init__(self, header, value):
        self.header = header
        self.value = value

    def describe(self):
        return "InvalidValue (%s, %s)" % (self.header, self.value)

    def get_details(self):
        return {}


class AreAllWellFormatted(object):
    """Specific matcher to check the correctness of formats of values

    This matcher checks the format of values of response headers.
    When checking the format of values of 'specific' headers such as
    X-Account-Meta-* or X-Object-Manifest for example, those values must be
    checked in each test code.
    """

    def match(self, actual):
        for key, value in six.iteritems(actual):
            if key in ('content-length', 'x-account-bytes-used',
                       'x-account-container-count', 'x-account-object-count',
                       'x-container-bytes-used', 'x-container-object-count')\
                and not value.isdigit():
                return InvalidFormat(key, value)
            elif key in ('content-type', 'date', 'last-modified',
                         'x-copied-from-last-modified') and not value:
                return InvalidFormat(key, value)
            elif key == 'x-timestamp' and not re.match("^\d+\.?\d*\Z", value):
                return InvalidFormat(key, value)
            elif key == 'x-copied-from' and not re.match("\S+/\S+", value):
                return InvalidFormat(key, value)
            elif key == 'x-trans-id' and \
                not re.match("^tx[0-9a-f]{21}-[0-9a-f]{10}.*", value):
                return InvalidFormat(key, value)
            elif key == 'accept-ranges' and not value == 'bytes':
                return InvalidFormat(key, value)
            elif key == 'etag' and not value.isalnum():
                return InvalidFormat(key, value)
            elif key == 'transfer-encoding' and not value == 'chunked':
                return InvalidFormat(key, value)

        return None


class InvalidFormat(object):
    """Informs an error message if a format of a certain header is invalid"""

    def __init__(self, key, value):
        self.key = key
        self.value = value

    def describe(self):
        return "InvalidFormat (%s, %s)" % (self.key, self.value)

    def get_details(self):
        return {}


class MatchesDictExceptForKeys(object):
    """Matches two dictionaries.

    Verifies all items are equals except for those identified by a list of keys
    """

    def __init__(self, expected, excluded_keys=None):
        self.expected = expected
        self.excluded_keys = excluded_keys if excluded_keys is not None else []

    def match(self, actual):
        filtered_expected = helpers.dict_subtract(self.expected,
                                                  self.excluded_keys)
        filtered_actual = helpers.dict_subtract(actual,
                                                self.excluded_keys)
        if filtered_actual != filtered_expected:
            return DictMismatch(filtered_expected, filtered_actual)


class DictMismatch(object):
    """Mismatch between two dicts describes deltas"""

    def __init__(self, expected, actual):
        self.expected = expected
        self.actual = actual
        self.intersect = set(self.expected) & set(self.actual)
        self.symmetric_diff = set(self.expected) ^ set(self.actual)

    def _format_dict(self, dict_to_format):
        # Ensure the error string dict is printed in a set order
        # NOTE(mtreinish): needed to ensure a deterministic error msg for
        # testing. Otherwise the error message will be dependent on the
        # dict ordering.
        dict_string = "{"
        for key in sorted(dict_to_format):
            dict_string += "'%s': %s, " % (key, dict_to_format[key])
        dict_string = dict_string[:-2] + '}'
        return dict_string

    def describe(self):
        msg = ""
        if self.symmetric_diff:
            only_expected = helpers.dict_subtract(self.expected, self.actual)
            only_actual = helpers.dict_subtract(self.actual, self.expected)
            if only_expected:
                msg += "Only in expected:\n  %s\n" % self._format_dict(
                    only_expected)
            if only_actual:
                msg += "Only in actual:\n  %s\n" % self._format_dict(
                    only_actual)
        diff_set = set(o for o in self.intersect if
                       self.expected[o] != self.actual[o])
        if diff_set:
            msg += "Differences:\n"
            for o in diff_set:
                msg += "  %s: expected %s, actual %s\n" % (
                    o, self.expected[o], self.actual[o])
        return msg

    def get_details(self):
        return {}
