# -*- coding:utf-8 -*-
"""
Function: configure_file.py moudle. This moudle mainly involves the
 exporting or Importing BIOS and iBMC Configuration Files function.
Copyright Information: xFusion Digital Technologies Co.,
 Ltd. All Rights Reserved © 2020-2021
"""
import os
import sys
from scripts import common_function


def configurefile_init(parser, parser_dict):
    """
    Function Description:initializing the Command for
    exporting or import BIOS and iBMC configuration files.
    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('config',
                                   help='export or import BIOS '
                                        'and iBMC configuration file')
    sub_parser.add_argument('-M',
                            dest='mode',
                            choices=['export', 'import'],
                            required=True,
                            help='import or export the configuration file')
    sub_parser.add_argument('-c',
                            dest='content',
                            required=False,
                            default=None,
                            help='path of the BIOS and iBMC'
                                 ' configuration file. On a local'
                                 ' file server, the configuration'
                                 ' file can be stored only in the'
                                 ' /tmp directory of iBMC, and the'
                                 ' path format is /tmp/file name.'
                                 ' On a remote file server, the'
                                 ' path format is protocol://'
                                 'User name:Password@IP address/'
                                 'Folder/File name. The file '
                                 'transfer protocols include the'
                                 ' following: sftp, https, nfs,' 
                                 ' cifs, scp.')
    sub_parser.add_argument('-F',
                            dest='file',
                            required=False,
                            help='the path of file. Local export or '
                                 'Local import:Folder/File name.\n\r')

    image_uri = {common_function.REQUIRED_FLAG: False,
                 common_function.HELP_INFO: 'path of the BIOS and iBMC'
                                            ' configuration file. On a local'
                                            ' file server, the configuration'
                                            ' file can be stored only in the'
                                            ' /tmp directory of iBMC, and the'
                                            ' path format is /tmp/file name.'
                                            ' On a remote file server, the'
                                            ' path format is server '
                                            'IP address/directory/file name.'}
    args_pro = {common_function.REQUIRED_FLAG: False}
    args_acc = {common_function.REQUIRED_FLAG: False}
    common_function.unpack_remote_server_path(sub_parser, image_uri,
                                              args_pro, args_acc)

    parser_dict['config'] = sub_parser

    return 'config'


def _resptaskparse(resp, client):
    """
    #====================================================================
    #   @Description:  parse response code and body
    #
    #====================================================================
    """

    taskid = resp['resource']['@odata.id']

    ssl_resp = client.get_resource(taskid)
    if ssl_resp is None:
        sys.exit(127)

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


def check_parameter(_, args):
    """
    Function Description:check CLI command
    Parameter:args object:CLI command
    parser object:subcommand ArgumentParser object
    """
    if (args.imageuri is not None or args.protocol is not None or
            args.accessuser is not None) and args.content is not None:
        print("Failure: -c contains the information of -i -PRO and -U. you can not use -c and -i -PRO -U both.")
        sys.exit(common_function.UREST_STATUS_CODE_2)
    if args.content is not None and not (common_function.verify_remote_server_info(args.content)
             or args.content.startswith("/tmp")):
        print('Failure: path of the BIOS and iBMC'
              ' configuration file. On a local'
              ' file server, the configuration'
              ' file can be stored only in the'
              ' /tmp directory of iBMC, and the'
              ' path format is /tmp/file name.'
              ' On a remote file server, the'
              ' path format is protocol://'
              'User name:Password@IP address/'
              'Folder/File name. The file '
              'transfer protocols include the'
              ' following: sftp, https, nfs,' 
              ' cifs, scp.')
        sys.exit(common_function.UREST_STATUS_CODE_2)
    if args.file is not None and os.path.splitext(args.file)[-1] != '.xml':
        print("Failure: -F indicates the path of the BIOS and iBMC"
              " configuration file. The file name extension must be .xml.")
        sys.exit(common_function.UREST_STATUS_CODE_2)


def is_interactive(args):
    """
    Function Description:check CLI command
    Parameter:args object:CLI command
    parser object:subcommand ArgumentParser object
    """
    if args.content is not None:
        return False
    return True


def configurefile(client, args):
    """
    #==========================================================================
    #   @Method:  export or import BIOS and BMC configuration file
    #   @Param:
    #   @Return:
    #   @author:
    #   @Modify: Modify the variable name of the receiving progress
    #   @Modify: The local import and export functions are added.
    #==========================================================================
    """
    file_path = get_file_path(client, args)
    slotid = client.get_slotid()
    if slotid is None:
        return None
    manage_url = '/redfish/v1/Managers/%s' % slotid
    manage_resp = client.get_resource(manage_url)
    if manage_resp is None:
        return None
    if manage_resp.get('resource', {}).get('Actions', {}).get('Oem', {}).get(common_function.COMMON_KEY):
        server_type = common_function.COMMON_KEY
    else:
        server_type = common_function.COMMON_KEY_XFUSION
    url_dict = {
        'export': '/redfish/v1/Managers/%s/Actions/Oem/%s/Manager.'
                  'ExportConfiguration' % (slotid, server_type),
        'import': '/redfish/v1/Managers/%s/Actions/Oem/%s/Manager.'
                  'ImportConfiguration' % (slotid, server_type)}
    payload = {"Type": "URI", "Content": file_path}

    resp = client.create_resource(url_dict.get(args.mode), payload)

    if resp is None:
        return None

    if resp['status_code'] != 202:
        error_message(resp['message']['error']['@Message.ExtendedInfo'],
                      resp['status_code'],
                      args.mode)
        return resp
    resp_task = client.print_task_prog(resp, flag="config")
    if resp_task is None:
        return None
    if resp_task == 'Exception':
        _resptaskparse(resp, client)
        sys.exit(144)
    if resp_task == 'Completed':
        if args.mode == 'export' and args.file is not None:
            common_function.export_local_path(client, slotid, file_path, args)
        sys.stdout.write('Success: successfully completed request\n')
        sys.stdout.flush()
    return resp


def get_file_path(client, args):
    """
    Function Description: get file path
    Parameter:client redfishClient
    args object:CLI command
    Return Value: file_path str: file path
    """
    if args.content is not None:
        file_path = args.content
    elif args.imageuri is not None:
        file_path = common_function.splice_remote_server_path(args)
    else:
        if args.mode == 'export':
            file_path = common_function.set_file_path(args.file)
        else:
            file_path = common_function.import_file_path(client, args.file)

    if file_path is None:
        sys.exit(common_function.UREST_STATUS_CODE_2)

    return file_path


def error_message(message, error_code, mode):
    """
    #==========================================================================
    #   @Method:  print error message
    #   @Param:
    #   @Return:
    #   @author:
    #==========================================================================
    """
    if error_code == 404:
        print("Failure: resource was not found")
    elif error_code == 400:
        messageid = message[0]['MessageId'].split('.')[-1]

        if messageid in ['ConfigurationExportingErr',
                         'ConfigurationImportingErr']:
            print("Failure: %s" %
                  common_function.change_message(message[0]['Message']))
        elif messageid in ['InvalidPath', 'PropertyValueFormatError']:
            if mode == 'export':
                print("Failure: export failed due to invalid path")
            else:
                print("Failure: import failed due to invalid path")
        elif messageid == 'FileTransferErrorDesc':
            print("Failure: %s" % (
                common_function.change_message(message[0]['Message']).replace(
                    'Details', 'details')))
        else:
            print("Failure: %s" % (
                common_function.change_message(message[0]['Message'])))
    else:
        print("Failure: the request failed due to an internal service error")
