# Copyright 2013 Red Hat, Inc.
# All Rights Reserved.
#
# 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 json
import requests

from six.moves import urllib

from config_tempest.constants import LOG
from config_tempest.services.base import VersionedService


class IdentityService(VersionedService):
    def __init__(self, name, s_type, service_url, token,
                 disable_ssl_validation, client=None, **kwargs):
        super(IdentityService, self).__init__(
            name, s_type, service_url, token, disable_ssl_validation,
            client, **kwargs)
        self.extensions_v3 = []
        version = ''
        if 'v2' in self.service_url:
            version = '/v2.0'
            url_parse = urllib.parse.urlparse(self.service_url)
            self.service_url = '{}://{}{}'.format(url_parse.scheme,
                                                  url_parse.netloc, version)

    def set_extensions(self):
        if 'v2' in self.service_url:
            body = self.do_get(self.service_url + '/extensions')
            body = json.loads(body)
            values = body['extensions']['values']
            self.extensions = list(map(lambda x: x['alias'], values))
            return
        # Keystone api changed in v3, the concept of extensions changed. Right
        # now, all the existing extensions are part of keystone core api, so,
        # there's no longer the /extensions endpoint. The extensions that are
        # stable, are enabled by default, the ones marked as experimental are
        # disabled by default. Checking the tempest source, there's no test
        # pointing to extensions endpoint, so I am very confident that this
        # will not be an issue. If so, we need to list all the /OS-XYZ
        # extensions to identify what is enabled or not. This would be a manual
        # check every time keystone change, add or delete an extension, so I
        # rather prefer to set empty list here for now.
        self.extensions = []

    def get_service_extension_key(self):
        return 'api_extensions'

    def get_supported_versions(self):
        return ['v2', 'v3']

    @staticmethod
    def get_service_type():
        return ['identity']

    def set_identity_v3_extensions(self):
        """Returns discovered identity v3 extensions

        As keystone V3 uses a JSON Home to store the extensions.
        This method implements a different discovery method.

        :return: A list with the discovered extensions
        """
        try:
            r = requests.get(self.service_url,
                             verify=False,
                             headers={'Accept': 'application/json-home'})
            # check for http status
            r.raise_for_status()
        except requests.exceptions.HTTPError:
            LOG.warning("Request on service '%s' with url '%s' failed, "
                        "checking for v3", 'identity', self.service_url)
            if 'v3' not in self.service_url:
                self.service_url = self.service_url + '/v3'
                r = requests.get(self.service_url,
                                 verify=False,
                                 headers={'Accept': 'application/json-home'})

        ext_h = 'https://docs.openstack.org/api/openstack-identity/3/ext/'
        content = r.content.decode('utf-8')
        res = [x for x in json.loads(content)['resources'].keys()]
        ext = [ex for ex in res if 'ext' in ex]
        ext = [str(e).replace(ext_h, '').split('/')[0] for e in ext]
        self.extensions_v3 = list(set(ext))

    def set_versions(self):
        super(IdentityService, self).set_versions(top_level=False)

    def get_extensions(self):
        all_ext_lst = self.extensions + self.extensions_v3
        return list(set(all_ext_lst))

    def deserialize_versions(self, body):
        try:
            versions = []
            for v in body['versions']['values']:
                # TripleO is in transition to v3 only, so the environment
                # still returns v2 versions even though they're deprecated.
                # Therefor pick only versions with stable status.
                if v['status'] == 'stable':
                    versions.append(v['id'])
            return versions
        except KeyError:
            return [body['version']['id']]

    def set_default_tempest_options(self, conf):
        """Set keystone feature flags based upon version ID."""
        supported_versions = self.get_versions()

        if supported_versions:
            major, minor = supported_versions[0].split('.')
            conf.set('identity', 'auth_version', major)

        if len(supported_versions) <= 1:
            return
        for version in supported_versions:
            major, minor = version.split('.')[:2]
            # Enable the domain specific roles feature flag.
            # For more information see:
            # https://docs.openstack.org/api-ref/identity/v3
            if major == 'v3' and int(minor) >= 6:
                conf.set('identity-feature-enabled',
                         'forbid_global_implied_dsr',
                         'True')
