#   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.
#
'''ModelArts service v1 action implementations'''
import logging

from osc_lib import utils
from osc_lib.command import command
from otcextensions.common import sdk_utils

from otcextensions.i18n import _

LOG = logging.getLogger(__name__)


def _flatten_output(obj):
    data = {
        'service_name': obj.service_name,
        'service_id': obj.service_id,
    }
    return data


def _get_columns(item):
    column_map = {
    }
    return sdk_utils.get_osc_show_columns_for_sdk_resource(item, column_map)


class DeleteService(command.Command):
    _description = _('Delete ModelArts Service')

    def get_parser(self, prog_name):
        parser = super(DeleteService, self).get_parser(prog_name)
        parser.add_argument(
            'service_id',
            metavar='<service_id>',
            help=_('ID of the service to delete.')
        )
        return parser

    def take_action(self, parsed_args):
        client = self.app.client_manager.modelarts
        client.delete_service(service=parsed_args.service_id, ignore_missing=False)


class UpdateConfig(command.Command):
    _description = _('Update Service Config')

    def get_parser(self, prog_name):
        parser = super(UpdateConfig, self).get_parser(prog_name)
        parser.add_argument(
            '--description',
            metavar='<description>',
            help=_('Service description, which contains a maximum of 100 characters. '
                   'If this parameter is not set, the service description is not updated.')
        )
        parser.add_argument(
            '--status',
            metavar='<status>',
            help=_('Service status. The value can be running or stopped. '
                   'If this parameter is not set, the service status is not changed.')
        )
        parser.add_argument(
            '--config',
            metavar='<config>',
            help=_('Service configuration. If this parameter is not set, the service is not updated.')
        )
        parser.add_argument(
            '--schedule',
            metavar='<schedule>',
            help=_('Service scheduling configuration, which can be configured only for real-time services. '
                   'By default, this parameter is not used.')
        )
        parser.add_argument(
            '--additional_properties',
            metavar='<additional_properties>',
            help=_('Additional service attribute, which facilitates service management')
        )
        return parser

    def take_action(self, parsed_args):
        client = self.app.client_manager.modelarts
        attrs = {}
        if parsed_args.description:
            attrs['description'] = parsed_args.description
        if parsed_args.status:
            attrs['status'] = parsed_args.status
        if parsed_args.config:
            attrs['config'] = parsed_args.config
        if parsed_args.schedule:
            attrs['schedule'] = parsed_args.schedule
        if parsed_args.additional_properties:
            attrs['additional_properties'] = parsed_args.additional_properties
        obj = client.update_config(**attrs)
        display_columns, columns = _get_columns(obj)
        data = utils.get_item_properties(obj, columns)
        client.update_config(service=parsed_args.service, ignore_missing=False)


class DeployModel(command.ShowOne):
    _description = _('Create a ModelArts service')

    def get_parser(self, prog_name):
        parser = super(DeployModel, self).get_parser(prog_name)
        parser.add_argument(
            '--service_name',
            metavar='<service_name>',
            required=True,
            help=_('Service name. The value can contain 1 to 64 visible characters, including Chinese characters. '
                   'Only letters, Chinese characters, digits, hyphens (-), and underscores (_) are allowed.')
        )
        parser.add_argument(
            '--description',
            metavar='<description>',
            required=False,
            help=_('Service description, which contains a maximum of 100 characters. '
                   'By default, this parameter is left blank.')
        )
        parser.add_argument(
            '--workspace_id',
            metavar='<workspace_id>',
            required=False,
            help=_('ID of the workspace to which a service belongs. '
                   'The default value is 0, indicating the default workspace.')
        )
        parser.add_argument(
            '--infer_type',
            metavar='<infer_type>',
            required=True,
            help=_('Inference mode. The value can be real-time, batch.')
        )
        parser.add_argument(
            '--vpc_id',
            metavar='<vpc_id>',
            required=False,
            help=_('ID of the VPC to which a real-time service instance is deployed. '
                   'By default, this parameter is left blank.')
        )
        parser.add_argument(
            '--subnet_network_id',
            metavar='<subnet_network_id>',
            required=False,
            help=_('ID of a subnet. By default, this parameter is left blank. This parameter is mandatory '
                   'when vpc_id is configured. Enter the network ID displayed in the subnet details '
                   'on the VPC management console ')
        )
        parser.add_argument(
            '--security_group_id',
            metavar='<security_group_id>',
            required=False,
            help=_('A security group is a virtual firewall that provides secure network access control policies for '
                   'service instances. ')
        )
        parser.add_argument(
            '--cluster_id',
            metavar='<cluster_id>',
            required=False,
            help=_('ID of a dedicated cluster. This parameter is left blank by default, '
                   'indicating that no dedicated cluster is used. When using the dedicated cluster to deploy services,'
                   ' ensure that the cluster status is normal. ')
        )
        parser.add_argument(
            '--config',
            metavar='<config>',
            required=True,
            help=_('Model running configuration. If infer_type is batch, you can configure only one model. '
                   'If you upload multiple models, the first model is used for creating a service by default. ')
        )
        parser.add_argument(
            '--schedule',
            metavar='<schedule>',
            required=False,
            help=_('Service scheduling configuration, which can be configured only for real-time services. '
                   'By default, this parameter is not used. ')
        )
        return parser

    def take_action(self, parsed_args):

        client = self.app.client_manager.modelarts

        attrs = {}

        if parsed_args.service_name:
            attrs['service_name'] = parsed_args.service_name
        if parsed_args.description:
            attrs['description'] = parsed_args.description
        if parsed_args.infer_type:
            attrs['infer_type'] = parsed_args.infer_type
        if parsed_args.workspace_id:
            attrs['workspace_id'] = parsed_args.workspace_id
        if parsed_args.vpc_id:
            attrs['vpc_id'] = parsed_args.vpc_id
        if parsed_args.subnet_network_id:
            attrs['subnet_network_id'] = parsed_args.subnet_network_id
        if parsed_args.security_group_id:
            attrs['security_group_id'] = parsed_args.security_group_id
        if parsed_args.cluster_id:
            attrs['cluster_id'] = parsed_args.cluster_id
        if parsed_args.config:
            attrs['config'] = parsed_args.config
        if parsed_args.schedule:
            attrs['schedule'] = parsed_args.schedule
        obj = client.deploy_model(**attrs)

        display_columns, columns = _get_columns(obj)
        data = utils.get_item_properties(obj, columns)

        return (display_columns, data)


class ShowService(command.ShowOne):
    _description = _('Show details of a Modelarts serivce')

    def get_parser(self, prog_name):
        parser = super(ShowService, self).get_parser(prog_name)
        parser.add_argument(
            'stream',
            metavar='<stream>',
            help=_('Enter stream name')
        )
        return parser

    def take_action(self, parsed_args):
        client = self.app.client_manager.modelarts

        data = client.show_service(
            service=parsed_args.service,
        )

        display_columns, columns = _get_columns(data)
        data = utils.get_item_properties(data, columns)

        return (display_columns, data)


class QueryDetails():
    pass


class QueryEventLogs():
    pass


class QueryList():
    pass


class QueryMonInfo():
    pass


class DeployModel():
    pass


class QueryPools():
    pass


class QuerySpecs():
    pass


class QueryUpdateLogs:
    pass


class Services(command.Lister):
    _description = _('Get properties of a service')
    columns = (
        'service_name',
        'service_id',
        'tenant',
        'project',
        'dimensions',
        'metric_name',
        'unit',
    )

    table_columns = (
        'service_name',
        'dimensions.name',
        'dimensions.value',
        'metric_name',
        'unit',
    )

    def get_parser(self, prog_name):
        parser = super(Services, self).get_parser(prog_name)
        return parser

    def take_action(self, parsed_args):
        client = self.app.client_manager.modelarts

        query = {}
        data = client.services(**query)

        table = (self.columns,
                 (utils.get_dict_properties(
                     _flatten_output(s), self.columns
                 ) for s in data))
        return table
