# -*- coding:utf-8 -*-
"""
Function: set_drive.py moudle. This moudle mainly involves the
Setting Physical Disk Attributes function.
Copyright Information: xFusion Digital Technologies Co.,
 Ltd. All Rights Reserved © 2017-2020
"""
import sys
from scripts import common_function


def setdrive_init(parser, parser_dict):
    """
    Function Description:initializing the Command for
    Setting Physical Disk Attributes
    Parameter:parser object: action object
    parser_dict dict: dictionary format of subcommand and ArgumentParser
    """
    sub_parser = parser.add_parser('setpdisk',
                                   help='''set physical disk information''')
    sub_parser.add_argument('-I', dest='driveid',
                            type=int, required=True,
                            help='''physicaldisk ID''')
    sub_parser.add_argument('-L', dest='indicatorled',
                            type=str, required=False,
                            choices=['Off', 'Blinking'],
                            help='''indicatorled''')
    sub_parser.add_argument('-T', dest='hotsparetype',
                            type=str, required=False,
                            choices=['None', 'Global', 'Dedicated'],
                            help='''hotspatetype''')
    sub_parser.add_argument('-CI', dest='controllerid',
                            type=int, required=False,
                            help='''controller ID''')

    sub_parser.add_argument('-LI', dest='logicaldriveid',
                            type=int, required=False,
                            help='''logicaldrive ID,''')

    sub_parser.add_argument('-S', dest='firmwarestatus',
                            type=str, required=False,
                            choices=['Online', 'Offline',
                                     'JBOD', 'UnconfiguredGood'],
                            help='''firmwarestatus''')
    parser_dict['setpdisk'] = sub_parser

    return 'setpdisk'


def check_drive_id_effective(client, driveid, slotid, url, id_list):
    """
    Function Description:Check the validity of the entered ID
    Parameter:client refishClient: class object
    driveid str: Drive ID
    slotid str: board ID.
    url list: Drive url
    id_list list: Drive ID list
    """
    chassis_url = "/redfish/v1/Chassis/" + slotid
    resp = client.get_resource(chassis_url)
    if resp is None:
        return None
    if resp['status_code'] != common_function.REDFISH_STATUS_CODE_200:
        if resp['status_code'] == common_function.REDFISH_STATUS_CODE_404:
            print('Failure: resource was not found')
        return resp

    # The item does not exist for resources of earlier versions.
    if resp['resource']['Links'].get('Drives') is None:
        print('Failure: resource was not found')
        return resp

    drive_array = resp['resource']['Links']['Drives']
    if drive_array:
        index = 0
        length = len(drive_array)
        while index < length:
            drive_url = drive_array[index]['@odata.id']
            # SD cards and SSD cards can be queried.
            if drive_url.find('SD') > 0 or drive_url.find('SSD') > 0:
                index += 1
                continue
            resp = client.get_resource(drive_url)
            if resp is None:
                return None
            if resp['status_code'] == common_function.REDFISH_STATUS_CODE_200:
                vendor_dict = common_function.get_vendor_value(resp)
                drive_id = vendor_dict['DriveID']
                id_list.append(str(drive_id))
                if driveid == drive_id:
                    url.append(drive_url)
                    break
            index += 1
    else:
        print('Failure: resource was not found')

    return resp


def drive_full_payload(payload, slotid, args):
    """
    Function Description:Fill the body.
    Parameter:payload dict: redfish interface Parameter
    slotid str: board ID.
    args object:CLI command
    """
    if args.indicatorled:
        payload['IndicatorLED'] = args.indicatorled

    if args.hotsparetype:
        payload['HotspareType'] = args.hotsparetype
        if args.hotsparetype == 'Dedicated':
            url = {common_function.COMMON_KEY: {"SpareforLogicalDrives": []}}
            system = '/redfish/v1/Systems/' + slotid
            controller = '/Storages/RAIDStorage' + str(args.controllerid)
            volumes = '/Volumes/LogicalDrive' + str(args.logicaldriveid)
            odata = system + controller + volumes
            url_vendor = url[common_function.COMMON_KEY]
            url_vendor['SpareforLogicalDrives'].append({'@odata.id': odata})
            payload['Oem'] = url

    if args.firmwarestatus:
        state = {common_function.COMMON_KEY: {}}
        state[common_function.COMMON_KEY]['FirmwareStatus'] \
            = args.firmwarestatus
        payload['Oem'] = state


def check_resp(messages):
    """
    Function Description:Process some success messages.
    Parameter:messages list: error message
    """
    err_format = '{0}{1}'
    print("Failure: some of the settings failed.possible causes "
          "include the following: ")
    length = len(messages)
    index = 0
    while index < length:
        if messages[index]['MessageId'] == 'Base.1.0.PropertyValueFormatError':
            message = "the value of -CI or -LI parameter is invalid"
        else:
            message = messages[index]['Message']
        check_info = message.replace("Oem/%s/" % common_function.COMMON_KEY,
                                     "")
        message = "%s%s" % \
                  (check_info[0].lower(), check_info[1:len(check_info) - 1])
        print(err_format.format('         ', message))
        index += 1


def check_error_info(messages):
    """
    Function Description:Process setting failure messages.
    Parameter:messages list: error message
    """
    err_format = '{0}{1}'
    index = 0
    while index < len(messages):
        if messages[index]['MessageId'] == 'Base.1.0.PropertyValueFormatError':
            message = "the value of -CI or -LI parameter is invalid"
        else:
            message = messages[index]['Message']
        check_info = message.replace("Oem/%s/" % common_function.COMMON_KEY,
                                     "")
        message = "%s%s" % \
                  (check_info[0].lower(), check_info[1:len(check_info) - 1])
        if index == 0:
            print(err_format.format('Failure: ', message))
        else:
            print(err_format.format('         ', message))
        index += 1


def check_parameter(parser, args):
    """
    Function Description:check CLI command
    Parameter:args object:CLI command
    parser object:subcommand ArgumentParser object
    """
    if common_function.all_none(args.indicatorled, args.hotsparetype,
                                args.firmwarestatus):
        parser.error('at least one parameter of -L,-T '
                     'and -S must be specified')
        # If the dedicated hot spare mode is used, you must enter the controller
        # ID and logical disk ID.
    if args.hotsparetype == "Dedicated":
        if (args.controllerid is None) or (args.logicaldriveid is None):
            parser.error("the value of -T parameter is Dedicated,"
                         "-CI and -LI parameter must be specified")
    elif args.controllerid is not None or args.logicaldriveid is not None:
        parser.error("the -CI or -LI parameter not required")


def setdrive(client, args):
    """
    Function Description:Setting Physical Disk Attributes
    Parameter:client refishClient: class object
    args object:CLI command
    """
    slotid = client.get_slotid()
    if slotid is None:
        return None

    # Physical disk ID validity check
    url = []
    id_list = []
    resp = check_drive_id_effective(client, args.driveid, slotid, url, id_list)
    if resp is None:
        return None
    # No physical disk
    if not id_list:
        print('Failure: resource was not found')
        sys.exit(common_function.UREST_STATUS_CODE_148)

    if not url:
        print('Failure: the value of -I parameter is invalid, '
              'chooes from ' + '<' + ','.join(id_list) + '>')
        sys.exit(common_function.UREST_STATUS_CODE_2)
    if resp['status_code'] == common_function.REDFISH_STATUS_CODE_200:
        # Combine body
        payload = {}
        drive_full_payload(payload, slotid, args)
        resp = client.set_resource(url[0], payload, None, 30)
        if resp is None:
            return None
        if resp['status_code'] == common_function.REDFISH_STATUS_CODE_200:
            if resp['resource'].get('@Message.ExtendedInfo') is not None:
                messages = resp['resource']['@Message.ExtendedInfo']
                check_resp(messages)
                sys.exit(common_function.UREST_STATUS_CODE_144)
            else:
                print('Success: successfully completed request')
        elif resp['status_code'] == common_function.REDFISH_STATUS_CODE_400:
            messages = resp['message']['error']['@Message.ExtendedInfo']
            check_error_info(messages)

    return resp
