# -*- coding:utf-8 -*-
"""
Function: collect_sel.py moudle. This moudle mainly involves the
 collecting iBMC SEL Logs function.
Copyright Information: xFusion Digital Technologies Co.,
 Ltd. All Rights Reserved © 2020-2021
"""
import time

import sys
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"
error_message_list = ['DumpExportingErr', 'UpgradingErr',
                      'InsufficientMemoryErr']
error_path_list = ['InvalidPath', 'PropertyValueFormatError']


def collectsel_init(parser, parser_list):
    """
    :Function:Collect SEL subcommand
    :param parser:major command argparser
    :param parser_list:save subcommand parser list
    :return:'collectsel'
    """
    # Modify: 2019.4.28 The help information is optimized.
    sub_parser = parser.add_parser('collectsel',
                                   help='''get SEL information''')
    sub_parser.add_argument('-F', dest='file',
                            type=str, required=True,
                            help='''the path of file.
                                   Local export:Folder/File name.
                                   \n\r''')
    parser_list['collectsel'] = sub_parser

    return 'collectsel'


def collectsel(client, args):
    """
    :Function:Collect SEL
    :param client:RedfishClient object
    :param parser:subcommand argparser.
                  Export error messages when parameters are incorrect.
    :param args:parameter list
    :return:
    """
    # Obtain the slot number.
    slotid = client.get_slotid()

    if slotid is None:
        return None

    # Check the path.
    file_dir = path.dirname(args.file)
    if not path.exists(file_dir):
        print("Failure: the local path does not exist")
        return None

    if path.isdir(args.file):
        print("Failure: please specify a file name")
        return None

    file_name = path.split(args.file)[1]
    # Construct payload.
    payload = {"Type": "URI", "Content": "/tmp/" + file_name}
    # Construct the URI of POST operations.
    url = "/redfish/v1/Systems/%s/LogServices/Log1/Actions/Oem/%s" \
          "/LogService.CollectSel" \
          % (slotid, common_function.COMMON_KEY)

    # Perform POST operations. resp indicates the entire response information,
    # including the response body and the status code.
    resp = client.create_resource(url, payload)
    if resp is None:
        return None

    # The latency is 2 seconds. Wait until the task percentage value changes
    # to a value greater than or equal to 0%, and display information.
    time.sleep(2)
    if resp['status_code'] == 202:
        resp_task = client.print_task_prog(resp, flag="collectsel")
        if resp_task is None:
            return None

        # Handle exceptions.
        if resp_task == 'Exception':
            taskstate(client, resp)
            sys.exit(144)

        if resp_task == 'Completed':
            resp_collect = exportsel(client, slotid, file_name, args)
            return resp_collect
    elif resp['status_code'] == 404:
        print("Failure: resource was not found")
    elif resp['status_code'] == 400:
        error_message = resp['message']['error']['@Message.ExtendedInfo'][0]
        error_parse(error_message)
    else:
        messages = resp['message']['error']['@Message.ExtendedInfo']
        message = (messages[0]['Message']).lower()
        print('Failure: ' + message)

    return resp


def exportsel(client, slotid, file_name, args):
    """
    :param file_name:
    :Function:Export SEL to local
    :param client:RedfishClient object
    :param slotid:slot number
    :para file_name:saved local file name
    :param args:parameter list
    :return:
    """
    url = "/redfish/v1/Managers/%s/Actions/Oem/%s/" \
          "Manager.GeneralDownload" % (slotid, common_function.COMMON_KEY)
    payload = {"TransferProtocol": "HTTPS", "Path": "/tmp/" + file_name}
    resp = client.create_resource(url, payload)
    if resp is None:
        return None

    if resp.get('status_code', None) == 200:
        if creat_res_file(resp, args):
            print('Success: successfully completed request')
            sys.exit(0)
        else:
            sys.exit(2)
    elif resp['status_code'] == 404:
        print("Failure: resource was not found")
    elif resp['status_code'] == 400:
        error_message = resp['message']['error']['@Message.ExtendedInfo'][0]
        error_parse(error_message)
    else:
        messages = resp['message']['error']['@Message.ExtendedInfo']
        message = (messages[0]['Message']).lower()
        print('Failure: ' + message)

    return resp


def error_parse(error_message):
    """
    :Function:Display error information
    :param error_message:error message
    :return:
    """
    # Parameter verification
    if error_message is None:
        return None

    # Obtain the value of MessageId.
    messageid = error_message['MessageId'].split('.')[-1]
    # Obtain the value of formatted 'message'.
    message = error_message['Message'].lower()
    # Modify: 2019.6.19 Print error info.
    if message[-1] == '.':
        message = (message[:-1])
        print("Failure: %s" % message)
    # Display messages according to the specific MessageId values
    # (repeated operation, upgrade environment,
    # insufficient tmp directory memory)
    if messageid in error_message_list:
        print("Failure: %s" % message)
    elif messageid in error_path_list:
        print("Failure: export failed due to invalid path")

    return None


def taskstate(client, resp):
    """
    :Function:Handle task state
    :param client:RedfishClient object
    :param resp:response information
    :return:
    """
    # Obtain the task ID.
    taskid = resp['resource']['@odata.id']
    # Perform the GET operation again to obtain the message body.
    task_resp = client.get_resource(taskid)
    if task_resp is None:
        return None

    if task_resp['status_code'] != 200:
        messages = task_resp['message']['error']['@Message.ExtendedInfo']
        message = (messages[0]['Message']).lower()
        print('Failure: ' + message[:-1])
    else:
        message = (task_resp['resource']['Messages']['Message']).lower()
        print('Failure: ' + message[:-1])
    return task_resp


def creat_res_file(resp, args):
    """
    :Function:Export files
    :param resp:response information
    :param args:parameter list
    :return:
    """
    try:
        custom_bytes = resp['resource']
        custom_str = custom_bytes.decode(encoding='utf-8', errors='strict')
        common_function.write_file(file_path=args.file,
                                   file_content=custom_str)
    except OSError:
        print(FAIL)
        return False

    return True
