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


def setpsredundancy_init(parser, parser_dict):
    """
    Function Description:initializing the Command for
    Setting the PSU Redundancy Mode
    Parameter:parser object: action object
    parser_dict dict: dictionary format of subcommand and ArgumentParser
    """
    sub_parser = parser.add_parser('setpowerredun',
                                   help='''set power redundancy''')
    sub_parser.add_argument('-M', dest='expectedredundancy',
                            type=str, required=True,
                            choices=['Sharing', 'Failover'],
                            help='''expected redundancy mode''')
    sub_parser.add_argument('-N', dest='expectedactivepsu',
                            type=str, nargs='*',
                            help='''expected active PSU name,
                            for example: PSU1 PSU2 PSU3...''')
    parser_dict['setpowerredun'] = sub_parser

    return 'setpowerredun'


def print_error_message(resp):
    """
    Function Description:print error message
    Parameter:resp dict: redfish interface value
    """
    info = resp['message']['error']['@Message.ExtendedInfo'][0]
    str_format = '{0}: {1}'
    bmc_asmu = 'iBMC.1.0.ActiveStandbyModeUnsupport'
    bmc_deapsu = 'iBMC.1.0.DuplicateElemInActivePSU'

    if info['MessageId'] == 'iBMC.1.0.PsNotSupport':
        info['Message'] = "the PSU do not support the Failover redundancy"

    elif info['MessageId'] == 'iBMC.1.0.ActiveStandbyDisabled':
        asd = "setting of the power supply working mode is not supported"
        info['Message'] = asd

    elif info['MessageId'] == 'iBMC.1.0.ActivePsNotPosition':
        info['Message'] = "the active PSU is not specified"

    elif info['MessageId'] == 'iBMC.1.0.NoStandbyPsPosition':
        info['Message'] = "the standby PSU is not specified"

    elif info['MessageId'] == 'iBMC.1.0.ActivePsNotHealth':
        info['Message'] = "the active PSU is unhealthy"

    elif info['MessageId'] == 'iBMC.1.0.CurrentPowerHigh':
        str1 = "the current power exceeds 75% "
        str2 = "of the power ratings of all active PSUs"
        info['Message'] = str1 + str2

    elif info['MessageId'] == 'iBMC.1.0.ActivePsNotEnough':
        info['Message'] = "active PSUs are insufficient"

    elif bmc_asmu == info['MessageId']:
        info['Message'] = "the Failover redundancy is not supported"

    elif bmc_deapsu == info['MessageId']:
        info['Message'] = "the -N parameter contains duplicate values"

    print(str_format.format('Failure', info['Message']))


def check_args(args, ps_name, slotid, payload):
    """
    Function Description:Check input parameters.
    Parameter:args object:CLI command
    ps_name list:  powersupplies name
    slotid str: board id
    payload dict: redfish Parameter
    Return Value:False: The input parameter is incorrect;
    True: The input parameter is correct.
    """
    args_length = len(args.expectedactivepsu)
    ps_length = len(ps_name)
    # The configured number of PSUs exceeds the actual number of PSUs.
    if args_length > ps_length:
        print('Failure: the number of active PSU name exceeds the maximum')
        return False
    # Check the PSU settings
    index = 0
    count = 0
    chassis = '/redfish/v1/Chassis/'
    power = '/Power#/PowerSupplies/'
    while index < args_length:
        num = 0
        while num < ps_length:
            if args.expectedactivepsu[index] == ps_name[num]:
                odata_psu = "%s%s%s%s" % (chassis, slotid, power, str(num))
                payload.append({'@odata.id': odata_psu})
                count += 1
            num += 1
        index += 1
    # Check whether correct PSUs are matched.
    # If no, incorrect PSU names are entered.
    if count != args_length:
        print('Failure: the value of -N parameter is invalid')
        sys.exit(UREST_STATUS_CODE_2)
    return True


def check_result(resp):
    """
    Function Description:Check the setting results.
    Parameter:resp dict: redfish interface value
    """
    if resp is None:
        return resp

    if resp['status_code'] == REDFISH_STATUS_CODE_200:
        print('Success: successfully completed request')

    elif resp['status_code'] == REDFISH_STATUS_CODE_400:
        print_error_message(resp)

    return resp


def check_parameter(parser, args):
    """
    Function Description:check CLI command
    Parameter:args object:CLI command
    parser ArgumentParser: subcommand ArgumentParser object
    """
    # If the load-balancing mode is used
    if args.expectedredundancy == 'Sharing':
        # In load-balancing mode,
        # no specific PSU parameter needs to be imported.
        if args.expectedactivepsu is not None:
            parser.error('the -N parameter is not required')
    elif args.expectedredundancy == 'Failover':
        # You must import the configured PSU.
        if args.expectedactivepsu is None:
            parser.error('the -N parameter is required')
        len_psu = len(args.expectedactivepsu)
        if len_psu == 0:
            parser.error('the value of -N parameter is invalid')


def setpsredundancy(client, args):
    """
    Function Description:Setting the PSU Redundancy Mode
    Parameter:client refishClient: class object
    args object:CLI command
    """
    slotid = client.get_slotid()
    if slotid is None:
        return None

    url = "/redfish/v1/Chassis/" + slotid + "/Power"
    resp = client.get_resource(url)
    if resp is None:
        return None

    if resp['status_code'] == REDFISH_STATUS_CODE_200:
        if resp['resource']['PowerControl'][0].get('Oem') is None:
            print('Failure: resource was not found')
            sys.exit(UREST_STATUS_CODE_148)
        # Combine the URI.
        power_key = "PowerControl"
        payload = {
            power_key: [
                {
                    common_function.OEM_KEY: {
                        common_function.COMMON_KEY: {
                            "ExpectedRedundancy": {}
                        }
                    }
                }
            ]
        }
        oem_dict = payload[power_key][0][common_function.OEM_KEY]
        payload_inner_dic = oem_dict[common_function.COMMON_KEY]
        # If the load-balancing mode is used
        if args.expectedredundancy == 'Sharing':
            sharing = '/redfish/v1/Chassis/' + slotid + '/Power#/Redundancy/0'
            payload_inner_dic['ExpectedRedundancy']['@odata.id'] = sharing
        # If the active/standby mode is used
        elif args.expectedredundancy == 'Failover':
            failover = '/redfish/v1/Chassis/' + slotid + '/Power#/Redundancy/1'
            payload_inner_dic['ExpectedRedundancy']['@odata.id'] = failover

            # Query the name of the current PSU and put the data into the list.
            powersupplies = resp['resource']['PowerSupplies']
            ps_name = {}
            index = 0
            len_power = len(powersupplies)
            while index < len_power:
                ps_name[index] = powersupplies[index]['Name']
                index += 1
            # Convert the PSU input into the URI.
            payload_inner_dic['ExpectedActivePSU'] = []
            result = check_args(args, ps_name,
                                slotid, payload_inner_dic['ExpectedActivePSU'])
            if not result:
                return None

        resp = client.set_resource(url, payload)
        # Successful
        resp = check_result(resp)
        return resp

    if resp['status_code'] == REDFISH_STATUS_CODE_404:
        print('Failure: resource was not found')

    return resp
