# -*- coding:utf-8 -*-
"""
Function: set_kvm.py moudle. This moudle mainly involves the
Setting KVM Information function.
Copyright Information: xFusion Digital Technologies Co.,
 Ltd. All Rights Reserved © 2017-2020
"""
import sys
from scripts.common_function import REDFISH_STATUS_CODE_404
from scripts.common_function import REDFISH_STATUS_CODE_200
from scripts.common_function import REDFISH_STATUS_CODE_400
from scripts.common_function import UREST_STATUS_CODE_144
from scripts import common_function

FAILURE_MESS = 'Failure: some of the settings failed.\
 possible causes include the following: '


def setkvm_init(parser, parser_dict):
    """
    Function Description:initializing the Command for Setting KVM Information
    Parameter:parser object: action object
    parser_dict dict: dictionary format of subcommand and ArgumentParser
    """
    sub_parser = parser.add_parser('setkvm',
                                   help='''set KVM information''')
    sub_parser.add_argument('-ES', dest='EncryptionEnabled',
                            type=str, required=False,
                            choices=['False', 'True'],
                            help='''KVM encryption''')
    sub_parser.add_argument('-US', dest='USBEnabled',
                            type=str, required=False,
                            choices=['False', 'True'],
                            help='''persistent virtual keyboard and mouse''')
    sub_parser.add_argument('-to', dest='Timeout',
                            type=int, required=False,
                            help='''timeout period (min)''')
    parser_dict['setkvm'] = sub_parser

    return 'setkvm'


def check_parameter(parser, args):
    """
    Function Description:check CLI command
    Parameter:args object:CLI command
    parser object:subcommand ArgumentParser object
    """
    if args.USBEnabled is None and args.EncryptionEnabled is None \
            and args.Timeout is None:
        parser.error('at least one parameter is required')
    if args.Timeout is not None and (args.Timeout < 0 or args.Timeout > 480):
        parser.error('argument -to: invalid choice: %d (choose from 0 to 480)'
                     % args.Timeout)


def setkvm(client, args):
    """
    Function Description:Setting KVM Information
    Parameter:client refishClient:class object
    args object:CLI command
    """
    slotid = client.get_slotid()
    if slotid is None:
        return None
    url = "/redfish/v1/Managers/%s/Kvmservice" % slotid
    resp_kvm = client.get_resource(url)
    if resp_kvm is None:
        return None
    if resp_kvm['status_code'] == REDFISH_STATUS_CODE_200:
        # Set attributes.
        resp_kvm = set_encryption(url, client, args)
    if resp_kvm['status_code'] == REDFISH_STATUS_CODE_404:
        print('Failure: resource was not found')
    return resp_kvm


def set_encryption(url, client, args):
    """
    Function Description:Set resource information.
    Parameter:url str:url
    client refishClient:class object
    args object:CLI command
    """
    # Encapsulate the request body.
    ret = package_request(args)
    if ret is None:
        return None
    # Set resource attributes.
    resp_kvm = client.set_resource(url, ret)
    if resp_kvm is None:
        return None
    if resp_kvm['status_code'] == REDFISH_STATUS_CODE_200:
        flag = check_err_info(resp_kvm['resource'], resp_kvm['status_code'])
        if not flag:
            sys.exit(UREST_STATUS_CODE_144)
    elif resp_kvm['status_code'] == REDFISH_STATUS_CODE_400:
        check_err_info(resp_kvm['message']['error'], resp_kvm['status_code'])
    return resp_kvm


def check_err_info(resp_kvm, code_kvm):
    """
    Function Description:Determine whether all attributes are set successfully.
    Parameter:resp_kvm dict:redfish value
    code_kvm int:redfish code
    """
    flag = False
    err_message = resp_kvm.get("@Message.ExtendedInfo", "")
    # Determine whether the configuration is successful.
    if err_message == "":
        print('Success: successfully completed request')
        flag = True
    else:
        # Determine whether a permission problem occurs.
        #  The entire resource has only one type of permission.
        mess_id = err_message[0].get("MessageId", "")
        if mess_id in ["iBMC.1.0.PropertyModificationNeedPrivilege",
                       "Base.1.0.InsufficientPrivilege"]:
            print('Failure: you do not have the required permissions to '
                  'perform this operation')
        else:
            # Display 400 messages independently.
            resq_mess(err_message, code_kvm)
    return flag


def resq_mess(err_message, code_kvm):
    """
    Function Description:Response messages
    Parameter:err_message list:error messages
    code_kvm int:redfish code
    """
    if code_kvm == REDFISH_STATUS_CODE_200:
        print(FAILURE_MESS)
    else:
        sys.stdout.write('Failure: ')
    idx = 0
    while idx < len(err_message):
        mess_id = err_message[idx].get("MessageId", "")
        if mess_id == "iBMC.1.0.DisableKVMEncryptionFailed":
            message = err_message[idx].get('Resolution', "")
        else:
            message = err_message[idx].get('Message', "")
        # Display messages.
        message = "%s%s" % (message[0].lower(), message[1:len(message) - 1])
        message = message.replace("Oem/%s/" % common_function.COMMON_KEY, "")

        if code_kvm == REDFISH_STATUS_CODE_400 and idx == 0:
            print('%s' % message)
        else:
            print('         %s' % message)
        idx += 1


def package_request(args):
    """
    Function Description:Encapsulate the request body.
    Parameter:args object:CLI command
    """
    payload = {}
    if args.EncryptionEnabled is not None:
        payload["EncryptionEnabled"] = args.EncryptionEnabled == str(True)
    if args.USBEnabled is not None:
        payload["PersistentUSBConnectionEnabled"] = \
            args.USBEnabled == str(True)
    if args.Timeout is not None:
        payload["SessionTimeoutMinutes"] = args.Timeout
    return payload
