Ensure the specified policy is set

    name
        the name of a single policy to configure

    setting
        the configuration setting for the single named policy
        if this argument is used the computer_policy/user_policy arguments will be ignored

    policy_class
        the policy class of the single named policy to configure
        this can "machine", "user", or "both"

    computer_policy
        a dict of policyname: value pairs of a set of computer policies to configure
        if this argument is used, the name/setting/policy_class arguments will be ignored

    user_policy
        a dict of policyname: value pairs of a set of user policies to configure
        if this argument is used, the name/setting/policy_class arguments will be ignored

    cumulative_rights_assignments
        determine if any user right assignment policies specified will be cumulative
        or explicit

    adml_language
        the adml language to use for AMDX policy data/display conversions

def set_(name,
         setting=None,
         policy_class=None,
         computer_policy=None,
         user_policy=None,
         cumulative_rights_assignments=True,
         adml_language='en-US'):
    '''
    Ensure the specified policy is set

    name
        the name of a single policy to configure

    setting
        the configuration setting for the single named policy
        if this argument is used the computer_policy/user_policy arguments will be ignored

    policy_class
        the policy class of the single named policy to configure
        this can "machine", "user", or "both"

    computer_policy
        a dict of policyname: value pairs of a set of computer policies to configure
        if this argument is used, the name/setting/policy_class arguments will be ignored

    user_policy
        a dict of policyname: value pairs of a set of user policies to configure
        if this argument is used, the name/setting/policy_class arguments will be ignored

    cumulative_rights_assignments
        determine if any user right assignment policies specified will be cumulative
        or explicit

    adml_language
        the adml language to use for AMDX policy data/display conversions
    '''
    ret = {'name': name,
           'result': True,
           'changes': {},
           'comment': ''}
    policy_classes = ['machine', 'computer', 'user', 'both']
    if not setting and not computer_policy and not user_policy:
        msg = 'At least one of the parameters setting, computer_policy, or user_policy'
        msg = msg + ' must be specified.'
        ret['result'] = False
        ret['comment'] = msg
        return ret
    if setting and not policy_class:
        msg = 'A single policy setting was specified but the policy_class was not specified.'
        ret['result'] = False
        ret['comment'] = msg
        return ret
    if setting and (computer_policy or user_policy):
        msg = 'The setting and computer_policy/user_policy parameters are mutually exclusive.  Please'
        msg = msg + ' specify either a policy name and setting or a computer_policy and/or user_policy'
        msg = msg + ' dict'
        ret['result'] = False
        ret['comment'] = msg
        return ret
    if policy_class and policy_class.lower() not in policy_classes:
        msg = 'The policy_class parameter must be one of the following: {0}'
        ret['result'] = False
        ret['comment'] = msg
        return ret
    if not setting:
        if computer_policy and user_policy:
            policy_class = 'both'
        elif computer_policy:
            policy_class = 'machine'
        elif user_policy:
            policy_class = 'user'
        if computer_policy and not isinstance(computer_policy, dict):
            msg = 'The computer_policy must be specified as a dict.'
            ret['result'] = False
            ret['comment'] = msg
            return ret
        if user_policy and not isinstance(user_policy, dict):
            msg = 'The user_policy must be specified as a dict.'
            ret['result'] = False
            ret['comment'] = msg
            return ret
    else:
        user_policy = {}
        computer_policy = {}
        if policy_class.lower() == 'both':
            user_policy[name] = setting
            computer_policy[name] = setting
        elif policy_class.lower() == 'user':
            user_policy[name] = setting
        elif policy_class.lower() == 'machine' or policy_class.lower() == 'computer':
            computer_policy[name] = setting
    pol_data = {}
    pol_data['user'] = {'output_section': 'User Configuration',
                        'requested_policy': user_policy,
                        'policy_lookup': {}}
    pol_data['machine'] = {'output_section': 'Computer Configuration',
                           'requested_policy': computer_policy,
                           'policy_lookup': {}}

    for p_class, p_data in six.iteritems(pol_data):
        if p_data['requested_policy']:
            for policy_name, policy_setting in six.iteritems(p_data['requested_policy']):
                lookup = __salt__['lgpo.get_policy_info'](policy_name,
                                                          p_class,
                                                          adml_language=adml_language)
                if lookup['policy_found']:
                    pol_data[p_class]['policy_lookup'][policy_name] = lookup
                else:
                    ret['comment'] = ' '.join([ret['comment'], lookup['message']])
                    ret['result'] = False
    if not ret['result']:
        return ret

    current_policy = __salt__['lgpo.get'](policy_class=policy_class,
                                          adml_language=adml_language,
                                          hierarchical_return=False)
    log.debug('current policy == %s', current_policy)

    # compare policies
    policy_changes = []
    for policy_section, policy_data in six.iteritems(pol_data):
        pol_id = None
        if policy_data and policy_data['output_section'] in current_policy:
            for policy_name, policy_setting in six.iteritems(policy_data['requested_policy']):
                currently_set = False
                # Check Case sensitive first (faster)
                if policy_name in current_policy[policy_data['output_section']]:
                    currently_set = True
                    pol_id = policy_name
                # Check case insensitive
                elif policy_name.lower() in (k.lower() for k in current_policy[policy_data['output_section']]):
                    for p_name in current_policy[policy_data['output_section']]:
                        if policy_name.lower() == p_name.lower():
                            currently_set = True
                            pol_id = p_name
                            break
                # Check aliases
                else:
                    for alias in policy_data['policy_lookup'][policy_name]['policy_aliases']:
                        log.debug('checking alias %s', alias)
                        if alias in current_policy[policy_data['output_section']]:
                            currently_set = True
                            pol_id = alias
                            break
                if currently_set:
                    # compare
                    log.debug('need to compare %s from '
                              'current/requested policy', policy_name)
                    changes = False
                    requested_policy_json = salt.utils.json.dumps(policy_data['requested_policy'][policy_name], sort_keys=True).lower()
                    current_policy_json = salt.utils.json.dumps(current_policy[policy_data['output_section']][pol_id], sort_keys=True).lower()
                    policies_are_equal = False

                    requested_policy_check = salt.utils.json.loads(requested_policy_json)
                    current_policy_check = salt.utils.json.loads(current_policy_json)

                    # Compared dicts, lists, and strings
                    if isinstance(requested_policy_check, six.string_types):
                        policies_are_equal = requested_policy_check == current_policy_check
                    elif isinstance(requested_policy_check, list):
                        policies_are_equal = salt.utils.data.compare_lists(
                            requested_policy_check,
                            current_policy_check
                        ) == {}
                    elif isinstance(requested_policy_check, dict):
                        policies_are_equal = salt.utils.data.compare_dicts(
                            requested_policy_check,
                            current_policy_check
                        ) == {}

                    if not policies_are_equal:
                        additional_policy_comments = []
                        if policy_data['policy_lookup'][policy_name]['rights_assignment'] and cumulative_rights_assignments:
                            for user in policy_data['requested_policy'][policy_name]:
                                if user not in current_policy[policy_data['output_section']][pol_id]:
                                    changes = True
                                else:
                                    additional_policy_comments.append('"{0}" is already granted the right'.format(user))
                        else:
                            changes = True
                        if changes:
                            log.debug('%s current policy != requested policy',
                                      policy_name)
                            log.debug(
                                'we compared %s to %s',
                                requested_policy_json, current_policy_json
                            )
                            policy_changes.append(policy_name)
                        else:
                            if additional_policy_comments:
                                ret['comment'] = '"{0}" is already set ({1})\n'.format(policy_name, ', '.join(additional_policy_comments))
                            else:
                                ret['comment'] = '"{0}" is already set\n'.format(policy_name) + ret['comment']
                    else:
                        log.debug('%s current setting matches '
                                  'the requested setting', policy_name)
                        ret['comment'] = '"{0}" is already set\n'.format(policy_name) + ret['comment']
                else:
                    policy_changes.append(policy_name)
                    log.debug('policy %s is not set, we will configure it',
                              policy_name)
    if __opts__['test']:
        if policy_changes:
            ret['result'] = None
            ret['comment'] = 'The following policies are set to change:\n{0}'.format(
                    '\n'.join(policy_changes))
        else:
            ret['comment'] = 'All specified policies are properly configured'
    else:
        if policy_changes:
            _ret = __salt__['lgpo.set'](computer_policy=computer_policy,
                                        user_policy=user_policy,
                                        cumulative_rights_assignments=cumulative_rights_assignments,
                                        adml_language=adml_language)
            if _ret:
                ret['result'] = _ret
                ret['changes'] = salt.utils.dictdiffer.deep_diff(
                    current_policy,
                    __salt__['lgpo.get'](policy_class=policy_class,
                                         adml_language=adml_language,
                                         hierarchical_return=False))
                if ret['changes']:
                    ret['comment'] = 'The following policies changed:\n{0}' \
                                     ''.format('\n'.join(policy_changes))
                else:
                    ret['comment'] = 'The following policies are in the correct state:\n{0}' \
                                     ''.format('\n'.join(policy_changes))
            else:
                ret['result'] = False
                ret['comment'] = 'Errors occurred while attempting to configure policies: {0}'.format(_ret)

    return ret