# Copyright 2019 Red Hat, 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.


"""OpenStackClient plugin for the Shared File System Service."""

import logging

from osc_lib import utils

from manilaclient import api_versions
from manilaclient import client
from manilaclient.common import constants
from manilaclient import exceptions

LOG = logging.getLogger(__name__)

API_NAME = 'share'
API_VERSION_OPTION = 'os_share_api_version'
CLIENT_CLASS = 'manilaclient.v2.client.Client'
LATEST_VERSION = api_versions.MAX_VERSION
LATEST_MINOR_VERSION = api_versions.MAX_VERSION.split('.')[-1]

API_VERSIONS = {
    f'2.{i}': CLIENT_CLASS for i in range(0, int(LATEST_MINOR_VERSION) + 1)
}


def _get_manila_url_from_service_catalog(instance):
    service_type = constants.SFS_SERVICE_TYPE
    url = instance.get_endpoint_for_service_type(
        constants.SFS_SERVICE_TYPE,
        region_name=instance._region_name,
        interface=instance.interface,
    )
    # Fallback if cloud is using an older service type name
    if not url:
        url = instance.get_endpoint_for_service_type(
            constants.V2_SERVICE_TYPE,
            region_name=instance._region_name,
            interface=instance.interface,
        )
        service_type = constants.V2_SERVICE_TYPE
    if url is None:
        raise exceptions.EndpointNotFound(
            message="Could not find manila / shared-file-system endpoint in "
            "the service catalog."
        )
    return service_type, url


def make_client(instance):
    """Returns a shared file system service client."""
    requested_api_version = instance._api_version[API_NAME]

    endpoint_override = getattr(
        instance._cli_options, 'os_endpoint_override', None
    )
    if endpoint_override:
        manila_endpoint_url = endpoint_override
        service_type = constants.SFS_SERVICE_TYPE
    else:
        service_type, manila_endpoint_url = (
            _get_manila_url_from_service_catalog(instance)
        )

    instance.setup_auth()
    debugging_enabled = instance._cli_options.debug

    client_args = dict(
        session=instance.session,
        service_catalog_url=manila_endpoint_url,
        endpoint_type=instance.interface,
        region_name=instance.region_name,
        service_type=service_type,
        auth=instance.auth,
        http_log_debug=debugging_enabled,
        cacert=instance.cacert,
        cert=instance.cert,
        insecure=not instance.verify,
    )

    # Cast the API version into an object for further processing
    requested_api_version = api_versions.APIVersion(
        version_str=requested_api_version
    )

    max_version = api_versions.APIVersion(api_versions.MAX_VERSION)
    client_args.update(dict(api_version=max_version))
    temp_client = client.Client(max_version, **client_args)
    discovered_version = api_versions.discover_version(
        temp_client, requested_api_version
    )

    shared_file_system_client = utils.get_client_class(
        API_NAME, discovered_version.get_string(), API_VERSIONS
    )

    LOG.debug(
        'Instantiating Shared File System (share) client: %s',
        shared_file_system_client,
    )
    LOG.debug('Shared File System API version: %s', discovered_version)

    client_args.update(dict(api_version=discovered_version))
    return shared_file_system_client(**client_args)


def build_option_parser(parser):
    """Hook to add global options."""
    default_api_version = utils.env('OS_SHARE_API_VERSION') or LATEST_VERSION
    parser.add_argument(
        '--os-share-api-version',
        metavar='<shared-file-system-api-version>',
        default=default_api_version,
        choices=sorted(
            API_VERSIONS, key=lambda k: [int(x) for x in k.split('.')]
        ),
        help='Shared File System API version, default='
        + default_api_version
        + ' (version supported by both the client and the server) '
        '(Env: OS_SHARE_API_VERSION)',
    )
    parser.add_argument(
        "--os-endpoint-override",
        metavar="<endpoint-override>",
        default=utils.env(
            "OS_SHARED_FILE_SYSTEM_ENDPOINT_OVERRIDE",
            "OS_ENDPOINT_OVERRIDE",
            "OS_MANILA_BYPASS_URL",
            "MANILACLIENT_BYPASS_URL",
        ),
        help=(
            "Use this API endpoint instead of the Service Catalog. "
            "Defaults to env[OS_SHARED_FILE_SYSTEM_ENDPOINT_OVERRIDE]."
        ),
    )
    return parser
