# -*- coding:utf-8 -*-
"""
Function: get_bios_details.py moudle. This moudle mainly involves the
querying BIOS configuration details function.
Copyright Information: xFusion Digital Technologies Co.,
 Ltd. All Rights Reserved © 2018-2021
"""
import json
import sys
from json import dumps
from os import path
from scripts import common_function

FAIL = "Failure: insufficient permission for " \
       "the file or file name not specified, " \
       "perform this operation as system administrator/root, " \
       "or specify a file name"

bios_current_dic = None

BIOS_SETTING_INFO_NULL = "the server does not contain information" \
                         " about BIOS setup resource."
BIOS_SETTING_INFO_ATTRIBUTES_NULL = "the server does not contain information" \
                         " about BIOS setup resource Attributes."
SETTING_KEY = "ConfiguredValue"
CURRENT_KEY = "CurrentValue"
setting_attributes_dict = {}
bios_current_dic = {}


def getbiosdetails_init(parser, parser_dict):
    """
    Function Description:initializing the Command for
    querying BIOS configuration details.
    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('getbiosdetails',
                                   help='''get BIOS details''')
    sub_parser.add_argument('-A', dest='attribute',
                            required=False,
                            help='''attribute name''')
    sub_parser.add_argument('-F', dest='file',
                            required=False,
                            help='local file used to '
                                 'export the BIOS configuration.')

    parser_dict['getbiosdetails'] = sub_parser

    return 'getbiosdetails'


def init_setting_attributes(client, resp):
    """
    Function Description:get bios setting resource
    Parameter:client RefishClient: class object
              resp   dict:redfish result
    """
    try:
        set_url = resp['resource']['@Redfish.Settings']["SettingsObject"][
            "@odata.id"]
    except KeyError:
        return

    setting_resp = client.get_resource(set_url)
    if not setting_resp:
        raise common_function.CustomError(BIOS_SETTING_INFO_NULL)

    if setting_resp.get('status_code') != \
            common_function.REDFISH_STATUS_CODE_200:
        raise common_function.CustomError(setting_resp)

    setting_resource = setting_resp.get('resource')
    if not setting_resource:
        raise common_function.CustomError(BIOS_SETTING_INFO_NULL)

    global setting_attributes_dict
    setting_attributes_dict = setting_resource.get("Attributes", None)


def get_bios(client):
    """
    obtain current value
    :param client:
    :return:
    """
    info = None
    slotid = client.get_slotid()
    if slotid is None:
        return info, None

    url = "/redfish/v1/Systems/%s/Bios" % slotid
    resp = client.get_resource(url)
    if resp is None:
        return info, None

    if resp['status_code'] == 200:
        info = resp['resource'].get('Attributes', None)
        if info is None:
            common_function.print_info('no data available for the resource')
            return info, resp
        return info, resp
    if resp['status_code'] == 404:
        common_function.print_info('Failure: resource was not found')
    else:
        common_function.print_status_code(resp)

    return info, resp


def get_current_value(bios_dic, attribute_name):
    """
    get current value
    :param bios_dic: current bios dic
    :param attribute_name: bios attribute name
    :return: current_value
    """

    current_value = bios_dic[attribute_name]
    if attribute_name == "BMCWDTTimeout" and int(
            bios_dic[attribute_name]) < 15:
        current_value = str(int(bios_dic[attribute_name]) + 15)
    return current_value


def check_parameter(parser, args):
    """
    Function Description:check CLI command
    Parameter:args object:CLI command
    parser object:subcommand ArgumentParser object
    """
    if (args.attribute is None and args.file is None) \
            or (args.attribute is not None and args.file is not None):
        parser.error('Either -A or -F must be specified.')


def getbiosdetails(client, args):
    """
    Function Description:BIOS menu item query subcommand processing functions
    Parameter:client refishClient: class object
    args object:CLI command
    Modify: 2018.12.26 Default timeout parameter normalization.
    Return Value: resp dict:result of the redfish interface
    """
    global bios_current_dic
    bios_current_dic, resp = get_bios(client)
    if bios_current_dic is None:
        return resp

    if args.attribute is not None and args.attribute not in bios_current_dic:
        print('Failure: the attribute does not exist')
        sys.exit(common_function.UREST_STATUS_CODE_2)

    init_setting_attributes(client, resp)
    flag, resp = get_subcommand_request(client)
    if flag is True:
        update_resp(resp)
        if args.file is not None:
            export_json_file(resp, args)
        else:
            print_attribute_infor(resp, args)
        return resp

    raise common_function.CustomError(resp)


def check_resp(resp):
    """
     功能描述: 校验redfish接口返回来的值
     参数：resp (dict):redfish接口返回来的值
     返回值：flag (bool):请求是否成功
            resp (dict):url 请求回来的数据
     """
    if resp is not None and resp['status_code'] == 200:
        return True, resp
    return False, resp


def get_subcommand_request(client):
    """
    Function Description:Obtains the subcommand result from the
     specified Redfish interface.
    Parameter:client refishClient: class object
    Modify: 2019.7.19 Configuring the BIOS Parameters BMCWDTTimeout.
    Return Value: resp dict:result of the redfish interface
    """
    flag, resp = get_registries_uri_resp(client)
    if flag is True:
        flag, resp = get_memmber_uri_resp(client, resp)
        if flag is True:
            flag, resp = get_location_uri_resp(client, resp)
    return flag, resp


def export_json_file(resp, args):
    """
    Function Description:write the Redfish interface information obtained
     from the location URI to the JSON file.
    Parameter:resp dict: location uri Obtained Redfish Interface Information
    args object:CLI command
    Modify: 2019.7.19 Configuring the BIOS Parameters BMCWDTTimeout.
    Return Value: resp dict:result of the redfish interface
    """
    bios_info = resp['resource']
    result_flag = creat_res_file(args.file, bios_info)
    if result_flag:
        print('Success: successfully completed request')


def update_resp(resp):
    """
    Function Description:update resp
    Parameter:resp dict:redfish result
    """
    attributes_list = resp['resource']['RegistryEntries'][
        "Attributes"]
    # Update the value of CurrentValue in the exported BIOS details.
    for attribute in attributes_list:
        attribute_name = attribute.get("AttributeName", "")
        if attribute_name in bios_current_dic:
            # Configuring the BIOS Parameters BMCWDTTimeout.
            current_value = get_current_value(bios_current_dic,
                                              attribute_name)
            attribute[CURRENT_KEY] = current_value
            if setting_attributes_dict is not None:
                attribute[SETTING_KEY] = setting_attributes_dict.get(attribute_name)


def print_attribute_infor(resp, args):
    """
    Function Description:displays information about the
     BIOS configuration item name.
    Parameter:resp dict: location uri Obtained Redfish Interface Information
    args object:CLI command
    Modify: 2019.7.19 Configuring the BIOS Parameters BMCWDTTimeout.
    Return Value: resp dict:result of the redfish interface
    """
    attributes_list = resp['resource']['RegistryEntries']["Attributes"]

    for attribute in attributes_list:
        attribute_name = attribute.get("AttributeName", "")
        if args.attribute == attribute_name:
            print("-" * 100)
            print_resource(attribute, attribute_name)
            break


def get_registries_uri_resp(client):
    """
      功能描述：从url"/redfish/v1/Registries"的redfish 接口中请求到的结果
      参数：client (redfish_client):redfish接口
      返回值：check_resp(resp)：是否响应成功，已经实际获取到的值
      异常描述：None
      """
    url = "/redfish/v1/Registries"
    resp = client.get_resource(url)
    return check_resp(resp)


def get_location_uri_resp(client, resp):
    """
    功能描述：从url"/redfish/v1/RegistryStore/AttributeRegistries/en/
    BiosAttributeRegistry.vx_x_x.json"的redfish 接口中请求到的结果中取出id
    参数：client (redfish_client):redfish接口
          resp (dict):上级 get_memmber_uri_resp(client, resp)得到的结果
    返回值：check_resp(resp)：是否响应成功，已经实际获取到的值
    异常描述：None
    """
    location_uri = resp['resource']['Location'][0]["Uri"]
    resp = client.get_resource(location_uri, headers=None,
                               timeout=common_function.TIMEOUT_THIRTY)
    return check_resp(resp)


def get_memmber_uri_resp(client, resp):
    """
    功能描述：从url'"/redfish/v1/Registries/BiosAttributeRegistry.vx_x_x"'的
    redfish 接口中请求到的结果中取出id
    参数：resp (dict):上级url'/redfish/v1/Registries'的redfish 接口中请求到的结果
    返回值：check_resp(resp)：是否响应成功，已经实际获取到的值
    异常描述：None
    """
    memmbers = resp['resource']['Members']
    memmber_uri = ''
    for memmber in memmbers:
        if "BiosAttributeRegistry" in memmber["@odata.id"]:
            memmber_uri = memmber["@odata.id"]
            break
    resp = client.get_resource(memmber_uri)
    return check_resp(resp)


def print_resource(attribute, attribute_name):
    """
    #=====================================================================
    #   @Method:  Display the returned BIOS data.
    #   @Param:   info, BIOS message dictionary
    #             args, command parameter
    #   @Return:
    #   @author:
    #=====================================================================
    """
    display_name = attribute.get("DisplayName", "")
    help_text = attribute.get("HelpText", "")
    values_list = attribute.get("Value", [])
    format_str = "%-28s%-2s%-s"
    print(format_str % ('Attribute', ":", attribute_name))
    print(format_str % (CURRENT_KEY, ":", attribute.get(CURRENT_KEY, "")))
    print(format_str % (SETTING_KEY, ":",
                        attribute.get(SETTING_KEY, "")))
    if values_list:
        value_list = []
        for value in values_list:
            if "ValueName" in list(value.keys()):
                value_name = value["ValueName"]
                value_list.append(value_name)
        # Modify: 2019.10.24 python3 syntax switching
        optional_values = str(json.dumps(value_list))
        print(format_str % ('Value', ":", optional_values))
    else:
        if "Type" in list(attribute.keys()):
            attribute_type = attribute["Type"]
            if attribute_type == "Integer":
                lower_bound = str(attribute.get("LowerBound", 0))
                upper_bound = str(attribute.get("UpperBound", 0))
                print(format_str % ('UpperBound', ":", upper_bound))
                print(format_str % ('LowerBound', ":", lower_bound))
    print(format_str % ('DisplayName', ":", display_name))
    print(format_str % ('HelpText', ":", help_text))
    print("-" * 100)


def creat_res_file(file_path, bios_dict):
    """
    #=====================================================================
    #   @Method:  Export JSON files.
    #   @Param:   info, SP message dictionary
    #             args, command function parameter
    #   @Return:
    #   @author:
    #=====================================================================
    """
    # Check the path.
    file_dir = path.dirname(file_path)
    if path.exists(file_dir) is not True:
        print("Failure: the path does not exist")
        return False
    if path.isdir(file_path) is True:
        print("Failure: please specify a file name")
        return False
    try:
        if "RegistryEntries" in list(bios_dict.keys()):
            if "Dependencies" in list(bios_dict["RegistryEntries"].keys()):
                del bios_dict["RegistryEntries"]["Dependencies"]
            if "Menus" in list(bios_dict["RegistryEntries"].keys()):
                del bios_dict["RegistryEntries"]["Menus"]

        json_obj = dumps(bios_dict)
        common_function.write_file(file_path=file_path, file_content=json_obj)
    except OSError:
        print(FAIL)
        return False

    return True
