# By: Riasat Ullah
# This file contains variables and functions to handle organization member roles.

from utils import errors


# component, team, account user roles
admin_role = 'ADMIN'
limited_stakeholder_role = 'LIMITED_STAKEHOLDER'
limited_user_role = 'LIMITED_USER'
manager_role = 'MANAGER'
observer_role = 'OBSERVER'
owner_role = 'OWNER'
responder_role = 'RESPONDER'
restricted_access_role = 'RESTRICTED_ACCESS'
stakeholder_role = 'STAKEHOLDER'
user_role = 'USER'

# account level user role ids
owner_role_id = 1
admin_role_id = 2
user_role_id = 3
limited_user_role_id = 4
stakeholder_role_id = 5
limited_stakeholder_role_id = 6
manager_role_id = 7
responder_role_id = 8
observer_role_id = 9
restricted_access_role_id = 10

# account level user role mapping of role IDs to their role names
user_role_maps = {
    owner_role_id: owner_role,
    admin_role_id: admin_role,
    user_role_id: user_role,
    limited_user_role_id: limited_user_role,
    stakeholder_role_id: stakeholder_role,
    limited_stakeholder_role_id: limited_stakeholder_role,
    manager_role_id: manager_role,
    responder_role_id: responder_role,
    observer_role_id: observer_role,
    restricted_access_role_id: restricted_access_role
}

advanced_component_roles = [observer_role, responder_role, manager_role]

standard_to_advanced_role_id_maps = {
    limited_user_role_id: observer_role_id,
    user_role_id: responder_role_id
}

advanced_to_standard_role_id_maps = {
    restricted_access_role_id: limited_user_role_id,
    observer_role_id: limited_user_role_id,
    responder_role_id: user_role_id,
    manager_role_id: user_role_id
}


def get_role_id_from_name(role_name):
    '''
    Gets the role ID from the name of the role.
    :param role_name: (str or list) name of the role
    :return: (int) the role ID  | (list of int) role IDs
    '''
    inv_role_map = {v: k for k, v in user_role_maps.items()}

    if isinstance(role_name, str):
        if role_name in inv_role_map:
            return inv_role_map[role_name]
    elif isinstance(role_name, list):
        ids_ = [inv_role_map[name_] for name_ in role_name]
        return ids_
    raise LookupError(errors.err_user_role_invalid)


def get_standard_account_roles(with_stakeholders=False):
    '''
    Gets the account roles (names of the roles) that are allowed on an account
    without advanced roles permission.
    :return: (list of str) -> role names
    '''
    base_roles = [limited_user_role, user_role, admin_role, owner_role]
    if with_stakeholders:
        base_roles.append(limited_stakeholder_role)
        base_roles.append(stakeholder_role)
    return base_roles


def get_standard_account_role_ids(with_stakeholders=False):
    '''
    Gets the account roles (names of the roles) that are allowed on an account
    with standard roles permission.
    :return: (list of int) -> role IDs
    '''
    return get_role_id_from_name(get_standard_account_roles(with_stakeholders))


def get_standard_account_specific_role_ids():
    '''
    Get the list of role IDs thar are specific to the advanced account.
    :return: (list) of role IDs
    '''
    return [limited_user_role_id, user_role_id]


def get_advanced_account_roles(with_stakeholders=False):
    '''
    Gets the account roles (names of the roles) that are allowed on an account
    with advanced roles permission.
    :return: (list of str) -> role names
    '''
    base_roles = [restricted_access_role, observer_role, responder_role, manager_role, admin_role, owner_role]
    if with_stakeholders:
        base_roles.append(limited_stakeholder_role)
        base_roles.append(stakeholder_role)
    return base_roles


def get_advanced_account_role_ids(with_stakeholders=False):
    '''
    Gets the account roles (names of the roles) that are allowed on an account
    with advanced roles permission.
    :return: (list of int) -> role IDs
    '''
    return get_role_id_from_name(get_advanced_account_roles(with_stakeholders))


def get_advanced_account_specific_role_ids():
    '''
    Get the list of role IDs thar are specific to the advanced account.
    :return: (list) of role IDs
    '''
    return [restricted_access_role_id, observer_role_id, responder_role_id, manager_role_id]


def get_overlapping_user_role_ids():
    '''
    Gets the role IDs that overlap between standard and advanced permission accounts.
    :return: (list of int) role IDs
    '''
    return [limited_stakeholder_role_id, stakeholder_role_id, admin_role_id, owner_role_id]


def get_stakeholder_user_role_ids():
    '''
    Gets the IDs of the stakeholder roles only.
    :return: (list) of role IDs
    '''
    return [limited_stakeholder_role_id, stakeholder_role_id]


def is_upgrading_from_stakeholder(curr_role_id, new_role_id):
    '''
    Checks if an account is being upgrading from a stakeholder to a standard user.
    :param curr_role_id: current role ID of the user
    :param new_role_id: new role ID of the user
    :return: (boolean) True if it is being upgraded; False otherwise
    '''
    stk_rol_ids = get_stakeholder_user_role_ids()
    if curr_role_id in stk_rol_ids and new_role_id not in stk_rol_ids:
        return True
    return False


def is_downgrading_to_stakeholder(curr_role_id, new_role_id):
    '''
    Checks if an account is being downgrading to a stakeholder from a standard user.
    :param curr_role_id: current role ID of the user
    :param new_role_id: new role ID of the user
    :return: (boolean) True if it is being upgraded; False otherwise
    '''
    stk_rol_ids = get_stakeholder_user_role_ids()
    if curr_role_id not in stk_rol_ids and new_role_id in stk_rol_ids:
        return True
    return False
