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


def setldapgroup_init(parser, parser_dict):
    """
    Function Description:initializing the Command for
    Setting LDAP Group Information
    Parameter:parser object: action object
    parser_dict dict: dictionary format of subcommand and ArgumentParser
    Return Value: subcommand
    """
    sub_parser = parser.add_parser('setldapgroup',
                                   help='''set LDAP group information''')
    sub_parser.add_argument('-I', dest='memberid',
                            choices=['1', '2', '3', '4', '5', '6'],
                            required=True,
                            help='''LDAP controller ID''')
    sub_parser.add_argument('-G', dest='gid',
                            choices=['0', '1', '2', '3', '4'],
                            required=True,
                            help='''group ID''')
    sub_parser.add_argument('-N', dest='gname', type=str,
                            required=False,
                            help='''group name''')
    sub_parser.add_argument('-D', dest='gdomain', type=str,
                            required=False,
                            help='''group domain, example: CN=A,OU=B,DC=C''')
    sub_parser.add_argument('-RO', dest='grole', type=str,
                            required=False,
                            choices=['CommonUser', 'Operator', 'Administrator',
                                     'CustomRole1', 'CustomRole2',
                                     'CustomRole3', 'CustomRole4'],
                            help='''group role''')
    sub_parser.add_argument('-RU', dest='grule', type=str,
                            required=False, nargs='*',
                            choices=['Rule1', 'Rule2', 'Rule3'],
                            help='''group rule, the value can be empty or \
        a single rule, or be a two-rule or three-rule combination. \
        example value: 'Rule1','Rule2 Rule3' or 'Rule1 Rule2 Rule3' ''')
    sub_parser.add_argument('-i', dest='gface', type=str,
                            required=False, nargs='*',
                            choices=['Web', 'SSH', 'Redfish'],
                            help='''group interface, the value can be \
        empty or a single login inteface, or be a two-interface or  \
        three-interface combination, example value: 'Web',\
        'Web Redfish' or 'Web SSH Redfish' ''')

    parser_dict['setldapgroup'] = sub_parser

    return 'setldapgroup'


def _checkgrule(grule):
    """
    Function Description:check group rule
    Parameter: grule str: group rule
    """
    if len(grule) > 3:
        return False

    rule1 = 0
    rule2 = 0
    rule3 = 0

    for rule_info in grule:
        if rule_info == 'Rule1':
            rule1 = rule1 + 1
        if rule_info == 'Rule2':
            rule2 = rule2 + 1
        if rule_info == 'Rule3':
            rule3 = rule3 + 1

    if rule1 > 1 or rule2 > 1 or rule3 > 1:
        return False

    return True


def _checkinterface(interface):
    """
    Function Description:check interface
    Parameter: interface str: group interface
    """
    if len(interface) > 3:
        return False

    web = 0
    ssh = 0
    redfish = 0

    for interface_info in interface:
        if interface_info == 'Web':
            web = web + 1
        if interface_info == 'SSH':
            ssh = ssh + 1
        if interface_info == 'Redfish':
            redfish = redfish + 1

    if web > 1 or ssh > 1 or redfish > 1:
        return False
    return True


def print_err_fh(msgs_ldap):
    """
    Function Description:Print error information
    Parameter: msgs_ldap dict:redfish interface Value
    """
    if msgs_ldap is None:
        return
    for index, value in enumerate(msgs_ldap):
        len_msg = len(value['RelatedProperties'])
        if len_msg == 0:
            msg = value['MessageArgs'][1]
        else:
            msg = value['RelatedProperties'][0].replace('#/', '')
        if index == 0:
            print('Failure: invalid property %s value' % msg)
        else:
            print('         invalid property %s value' % msg)


def print_err_th(msgs_ldap):
    """
    Function Description:Print error information
    Parameter: msgs_ldap dict:redfish interface Value
    """
    if msgs_ldap is None:
        return
    error = 'Failure: some of the settings failed. '
    error = error + 'possible causes include the following:'
    print(error)
    for ldap_info in msgs_ldap:
        len_msg = len(ldap_info['RelatedProperties'])
        if len_msg == 0:
            msg = ldap_info['MessageArgs'][1]
        else:
            msg = ldap_info['RelatedProperties'][0].replace('#/', '')
        print('         invalid property %s value' % msg)


def get_payload(args):
    """
    Function Description:init payload
    Parameter: args object:CLI command
    """
    payload = {"LdapGroups": [{}, {}, {}, {}, {}]}
    gid = int(args.gid)
    role_dict = {"CommonUser": "Common User", "Operator": "Operator",
                 "Administrator": "Administrator",
                 "CustomRole1": "Custom Role 1",
                 "CustomRole2": "Custom Role 2",
                 "CustomRole3": "Custom Role 3",
                 "CustomRole4": "Custom Role 4"}
    # Modify: 2019.12.10 Delete the LDAP group When the value of -N is null.
    if args.gname is not None:
        if args.gname == "null":
            args.gname = None
        payload["LdapGroups"][gid]['GroupName'] = args.gname
    if args.gdomain is not None:
        payload["LdapGroups"][gid]['GroupDomain'] = args.gdomain
    if args.grole is not None:
        payload["LdapGroups"][gid]['GroupRole'] = role_dict.get(args.grole, "")
    if args.grule is not None:
        payload["LdapGroups"][gid]['GroupLoginRule'] = args.grule
    if args.gface is not None:
        payload["LdapGroups"][gid]['GroupLoginInterface'] = args.gface
    return payload


def setldapgroup(client, args):
    """
    Function Description:Setting LDAP Group Information
    Parameter:client refishClient: class object
    args object:CLI command
    Return Value: resp dict:result of the redfish interface
    """
    url = "/redfish/v1/AccountService/LdapService/LdapControllers/%s" \
          % args.memberid
    resp = client.get_resource(url)
    if resp is None or resp['status_code'] != \
            common_function.REDFISH_STATUS_CODE_200:
        return None
    payload = get_payload(args)
    resp = client.set_resource(url, payload)
    print_result(resp)
    return resp


def print_result(resp):
    """
    Function Description:Print result.
    Parameter: resp dict: redfish interface Value
    """
    if resp.get('status_code') == common_function.REDFISH_STATUS_CODE_200:
        # Some of the settings failed
        if resp['resource'].get('@Message.ExtendedInfo') is not None:
            messages = resp['resource']['@Message.ExtendedInfo']
            print_err_th(messages)
            sys.exit(common_function.UREST_STATUS_CODE_144)
        else:
            print('Success: successfully completed request')

    else:
        if resp.get('status_code') == common_function.REDFISH_STATUS_CODE_400:
            messages = resp['message']['error']['@Message.ExtendedInfo']
            print_err_fh(messages)


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.gname, args.gdomain, args.grole,
                                args.grule, args.gface):
        parser.error('at least one parameter of -N,-D,-RO,-Ru and '
                     '-i must be specified')
    if args.grule is not None and _checkgrule(args.grule) is False:
        parser.error('the value can be empty or a single rule, '
                     'or be a two-rule or three-rule combination. '
                     'example: "-RU ","-RU Rule1",'
                     '"-RU Rule2 Rule3 or "-RU Rule1 Rule2 Rule3" ')
    if args.gface is not None and _checkinterface(args.gface) is False:
        parser.error('the value can be empty or a single login inteface, '
                     'or be a two-interface or three-interface combination,'
                     ' example value: "-i Web",'
                     '"-i Web Redfish" or "-i Web SSH Redfish" ')
