# Copyright 2014 Amazon.com, Inc. or its affiliates. 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. A copy of
# the License is located at
#
#     http://aws.amazon.com/apache2.0/
#
# or in the "license" file accompanying this file. This file 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 logging

from awscli.customizations.commands import BasicCommand
from awscli.customizations.emr import config, configutils, emrutils, exceptions

LOG = logging.getLogger(__name__)


class Command(BasicCommand):
    region = None

    UNSUPPORTED_COMMANDS_FOR_RELEASE_BASED_CLUSTERS = set(
        [
            'install-applications',
            'restore-from-hbase-backup',
            'schedule-hbase-backup',
            'create-hbase-backup',
            'disable-hbase-backups',
        ]
    )

    def supports_arg(self, name):
        return any(x['name'] == name for x in self.ARG_TABLE)

    def _run_main(self, parsed_args, parsed_globals):
        self._apply_configs(
            parsed_args, configutils.get_configs(self._session)
        )
        self.region = emrutils.get_region(self._session, parsed_globals)
        self._validate_unsupported_commands_for_release_based_clusters(
            parsed_args, parsed_globals
        )
        return self._run_main_command(parsed_args, parsed_globals)

    def _apply_configs(self, parsed_args, parsed_configs):
        applicable_configurations = self._get_applicable_configurations(
            parsed_args, parsed_configs
        )

        configs_added = {}
        for configuration in applicable_configurations:
            configuration.add(
                self, parsed_args, parsed_configs[configuration.name]
            )
            configs_added[configuration.name] = parsed_configs[
                configuration.name
            ]

        if configs_added:
            LOG.debug("Updated arguments with configs: %s" % configs_added)
        else:
            LOG.debug("No configs applied")
        LOG.debug("Running command with args: %s" % parsed_args)

    def _get_applicable_configurations(self, parsed_args, parsed_configs):
        # We need to find the applicable configurations by applying
        # following filters:
        # 1. Configurations that are applicable to this command
        # 3. Configurations that are present in parsed_configs
        # 2. Configurations that are not present in parsed_args

        configurations = config.get_applicable_configurations(self)

        configurations = [
            x
            for x in configurations
            if x.name in parsed_configs and not x.is_present(parsed_args)
        ]

        configurations = self._filter_configurations_in_special_cases(
            configurations, parsed_args, parsed_configs
        )

        return configurations

    def _filter_configurations_in_special_cases(
        self, configurations, parsed_args, parsed_configs
    ):
        # Subclasses can override this method to filter the applicable
        # configurations further based upon some custom logic
        # Default behavior is to return the configurations list as is
        return configurations

    def _run_main_command(self, parsed_args, parsed_globals):
        # Subclasses should implement this method.
        # parsed_globals are the parsed global args (things like region,
        # profile, output, etc.)
        # parsed_args are any arguments you've defined in your ARG_TABLE
        # that are parsed.
        # parsed_args are updated to include any emr specific configuration
        # from the config file if the corresponding argument is not
        # explicitly specified on the CLI
        raise NotImplementedError("_run_main_command")

    def _validate_unsupported_commands_for_release_based_clusters(
        self, parsed_args, parsed_globals
    ):
        command = self.NAME

        if (
            command in self.UNSUPPORTED_COMMANDS_FOR_RELEASE_BASED_CLUSTERS
            and hasattr(parsed_args, 'cluster_id')
        ):
            release_label = emrutils.get_release_label(
                parsed_args.cluster_id,
                self._session,
                self.region,
                parsed_globals.endpoint_url,
                parsed_globals.verify_ssl,
            )
            if release_label:
                raise exceptions.UnsupportedCommandWithReleaseError(
                    command=command, release_label=release_label
                )


def override_args_required_option(argument_table, args, session, **kwargs):
    # This function overrides the 'required' property of an argument
    # if a value corresponding to that argument is present in the config
    # file
    # We don't want to override when user is viewing the help so that we
    # can show the required options correctly in the help
    need_to_override = False if len(args) == 1 and args[0] == 'help' else True

    if need_to_override:
        parsed_configs = configutils.get_configs(session)
        for arg_name in argument_table.keys():
            if arg_name.replace('-', '_') in parsed_configs:
                argument_table[arg_name].required = False
