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


def setlogicaldrive_init(parser, parser_dict):
    """
    Function Description:initializing the Command for
    setting Logical Disk Attributes.
    Parameter:parser object: action object
    parser_dict dict: dictionary format of subcommand and ArgumentParser
    Modify: 2019.4.28 The help information is optimized.
    Return Value: subcommand
    """
    sub_parser = parser.add_parser('setvdisk',
                                   help='''set virtual disk information''')
    sub_parser.add_argument('-CI',
                            dest='controllerid',
                            type=int, required=True,
                            help='''controller ID''')
    sub_parser.add_argument('-LI', dest='logicaldriveid',
                            type=int, required=True,
                            help='''logicalDrive ID''')
    sub_parser.add_argument('-N', dest='volumename',
                            type=str, required=False,
                            help='''vloume name''')
    sub_parser.add_argument('-RP', dest='defaultreadpolicy',
                            type=str, required=False,
                            choices=['NoReadAhead', 'ReadAhead'],
                            help='''defaultreadpolicy''')
    sub_parser.add_argument('-WP', dest='defaultwritepolicy',
                            type=str, required=False,
                            choices=['WriteThrough',
                                     'WriteBackWithBBU', 'WriteBack'],
                            help='''defaultwritepolicy''')
    sub_parser.add_argument('-CP', dest='defaultcachepolicy',
                            type=str, required=False,
                            choices=['CachedIO', 'DirectIO'],
                            help='''defaultcachepolicy''')
    sub_parser.add_argument('-BE', dest='bootenable',
                            type=str, required=False,
                            choices=['True'], help='''bootenable''')
    sub_parser.add_argument('-BGIE', dest='bgienable',
                            type=str, required=False,
                            choices=['True', 'False'],
                            help='''bgienable''')
    sub_parser.add_argument('-AP', dest='accesspolicy',
                            type=str, required=False,
                            choices=['ReadWrite', 'ReadOnly', 'Blocked'],
                            help='''accesspolicy''')
    sub_parser.add_argument('-SCS', dest='ssdcachingenable',
                            type=str, required=False,
                            choices=['True', 'False'],
                            help='''ssdcachingenable''')
    sub_parser.add_argument('-DCP', dest='drivecachepolicy',
                            type=str, required=False,
                            choices=['Unchanged', 'Enabled', 'Disabled'],
                            help='''drivecachepolicy''')
    parser_dict['setvdisk'] = sub_parser

    return 'setvdisk'


def check_error_info(messages):
    """
    #=====================================================================
    #   @Method:  Process setting failure messages.
    #   @Param:   messages, error message
    #   @Return:
    #   @author:
    #=====================================================================
    """
    err_format = '{0}{1}'
    index = 0
    while index < len(messages):
        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])
        # Display failure information in the first line.
        if index == 0:
            print(err_format.format('Failure: ', message))
        else:
            print(err_format.format('         ', message))
        index += 1


def check_resp(messages):
    """
    #=====================================================================
    #   @Method:  Process some successful messages.
    #   @Param:   messages, error message
    #   @Return:
    #   @Date: 2017 08 26
    #=====================================================================
    """
    err_format = '{0}{1}'
    print("Failure: some of the settings failed. possible causes include "
          "the following: ")
    length = len(messages)
    index = 0
    while index < length:
        check_info = messages[index]['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 str_to_bool(string):
    """
    #=========================================================================
    #   @Description:  str_to_bool
    #
    #   @author:
    #   @Date: 2017 08 21
    #=========================================================================
    """
    if string == 'True':
        return True
    return False


def full_payload(args, payload):
    """
    #=====================================================================
    #   @Method:  Set logical disk attributes.
    #   @Param:   args, parameter list
    #             payload, body
    #   @Return:
    #   @author:
    #=====================================================================
    """
    payload_vendor = payload['Oem'][common_function.COMMON_KEY]
    if args.volumename:
        payload_vendor['VolumeName'] = args.volumename

    # Default read policy
    if args.defaultreadpolicy:
        payload_vendor['DefaultReadPolicy'] = args.defaultreadpolicy
    # Default write policy
    if args.defaultwritepolicy:
        value = args.defaultwritepolicy
        payload_vendor['DefaultWritePolicy'] = value
    # Default cache policy
    if args.defaultcachepolicy:
        value = args.defaultcachepolicy
        payload_vendor['DefaultCachePolicy'] = value

    if args.bootenable:
        value = str_to_bool(args.bootenable)
        payload_vendor['BootEnable'] = value

    if args.bgienable:
        value = str_to_bool(args.bgienable)
        payload_vendor['BGIEnable'] = value

    if args.accesspolicy:
        payload_vendor['AccessPolicy'] = args.accesspolicy

    if args.ssdcachingenable:
        value = str_to_bool(args.ssdcachingenable)
        payload_vendor['SSDCachingEnable'] = value

    if args.drivecachepolicy:
        payload_vendor['DriveCachePolicy'] = args.drivecachepolicy


def set_logicaldrive(client, args, url):
    """
    #=====================================================================
    #   @Method:  Set logical disk attributes.
    #   @Param:   client, RedfishClient object
    #              args, parameter list
    #             url, Set the logical disk URL.
    #   @Return:
    #   @Date: 2017 8 27
    #=====================================================================
    """
    payload = {'Oem': {common_function.COMMON_KEY: {}}}
    full_payload(args, payload)
    resp = client.set_resource(url, payload, None, 30)
    if resp is None:
        return None

    if resp['status_code'] == 200:
        if resp['resource'].get('@Message.ExtendedInfo') is not None:
            messages = resp['resource']['@Message.ExtendedInfo']
            check_resp(messages)
            sys.exit(144)
        else:
            print('Success: successfully completed request')

    elif resp['status_code'] == 400:
        messages = resp['message']['error']['@Message.ExtendedInfo']
        check_error_info(messages)

    return resp


def check_parameter(parser, args):
    """
    Function Description:check CLI command
    Parameter:args object:CLI command
    parser object:subcommand ArgumentParser object
    """
    if not (args.volumename or args.defaultreadpolicy
            or args.defaultwritepolicy or args.defaultcachepolicy
            or args.bootenable or args.bgienable or args.accesspolicy
            or args.ssdcachingenable or args.drivecachepolicy):
        parser.error('at least one parameter must be specified')


def setlogicaldrive(client, args):
    """
    #=====================================================================
    #   @Method:  Set logical disk subcommand processing functions.
    #   @Param:   client, RedfishClient object
    #             parser, subcommand argparser. Export error messages
    when parameters are incorrect.
    #             args, parameter list
    #   @Return:
    #   @author:
    #=====================================================================
    """
    slotid = client.get_slotid()
    if slotid is None:
        return None

    # Determine whether a storage system exists.
    systems = "/redfish/v1/Systems/" + slotid
    storage = "/Storages/RAIDStorage" + str(args.controllerid)
    resp = client.check_storages(systems, storage, '-CI')
    if resp is None:
        return None

    if resp['status_code'] == 200:
        logical = "/Volumes/LogicalDrive" + str(args.logicaldriveid)
        url = systems + storage + logical
        #  Construct the body.
        resp = client.get_resource(url)
        if resp is None:
            return None

        if resp['status_code'] == 404:
            print('Failure: the value of -LI parameter is invalid')
            sys.exit(UREST_STATUS_CODE_2)
        if resp['status_code'] == 200:
            return set_logicaldrive(client, args, url)
    return resp
