r'''
    Set the value of webconfiguration settings.

    :param str name: The name of the IIS PSPath containing the settings.
        Possible PSPaths are :
        MACHINE, MACHINE/WEBROOT, IIS:\, IIS:\Sites\sitename, ...
    :param str location: The location of the settings.
    :param dict settings: Dictionaries of dictionaries.
        You can match a specific item in a collection with this syntax inside a key:
        'Collection[{name: site0}].logFile.directory'

    Example of usage for the ``MACHINE/WEBROOT`` PSPath:

    .. code-block:: yaml

        MACHINE-WEBROOT-level-security:
          win_iis.webconfiguration_settings:
            - name: 'MACHINE/WEBROOT'
            - settings:
                system.web/authentication/forms:
                  requireSSL: True
                  protection: "All"
                  credentials.passwordFormat: "SHA1"
                system.web/httpCookies:
                  httpOnlyCookies: True

    Example of usage for the ``IIS:\Sites\site0`` PSPath:

    .. code-block:: yaml

        site0-IIS-Sites-level-security:
          win_iis.webconfiguration_settings:
            - name: 'IIS:\Sites\site0'
            - settings:
                system.webServer/httpErrors:
                  errorMode: "DetailedLocalOnly"
                system.webServer/security/requestFiltering:
                  allowDoubleEscaping: False
                  verbs.Collection:
                    - verb: TRACE
                      allowed: False
                  fileExtensions.allowUnlisted: False

    Example of usage for the ``IIS:\`` PSPath with a collection matching:

    .. code-block:: yaml

        site0-IIS-level-security:
          win_iis.webconfiguration_settings:
            - name: 'IIS:\'
            - settings:
                system.applicationHost/sites:
                  'Collection[{name: site0}].logFile.directory': 'C:\logs\iis\site0'

    Example of usage with a location:

    .. code-block:: yaml

        site0-IIS-location-level-security:
          win_iis.webconfiguration_settings:
            - name: 'IIS:/'
            - location: 'site0'
            - settings:
              system.webServer/security/authentication/basicAuthentication:
                enabled: True

def webconfiguration_settings(name, location='', settings=None):
    r'''
    Set the value of webconfiguration settings.

    :param str name: The name of the IIS PSPath containing the settings.
        Possible PSPaths are :
        MACHINE, MACHINE/WEBROOT, IIS:\, IIS:\Sites\sitename, ...
    :param str location: The location of the settings.
    :param dict settings: Dictionaries of dictionaries.
        You can match a specific item in a collection with this syntax inside a key:
        'Collection[{name: site0}].logFile.directory'

    Example of usage for the ``MACHINE/WEBROOT`` PSPath:

    .. code-block:: yaml

        MACHINE-WEBROOT-level-security:
          win_iis.webconfiguration_settings:
            - name: 'MACHINE/WEBROOT'
            - settings:
                system.web/authentication/forms:
                  requireSSL: True
                  protection: "All"
                  credentials.passwordFormat: "SHA1"
                system.web/httpCookies:
                  httpOnlyCookies: True

    Example of usage for the ``IIS:\Sites\site0`` PSPath:

    .. code-block:: yaml

        site0-IIS-Sites-level-security:
          win_iis.webconfiguration_settings:
            - name: 'IIS:\Sites\site0'
            - settings:
                system.webServer/httpErrors:
                  errorMode: "DetailedLocalOnly"
                system.webServer/security/requestFiltering:
                  allowDoubleEscaping: False
                  verbs.Collection:
                    - verb: TRACE
                      allowed: False
                  fileExtensions.allowUnlisted: False

    Example of usage for the ``IIS:\`` PSPath with a collection matching:

    .. code-block:: yaml

        site0-IIS-level-security:
          win_iis.webconfiguration_settings:
            - name: 'IIS:\'
            - settings:
                system.applicationHost/sites:
                  'Collection[{name: site0}].logFile.directory': 'C:\logs\iis\site0'

    Example of usage with a location:

    .. code-block:: yaml

        site0-IIS-location-level-security:
          win_iis.webconfiguration_settings:
            - name: 'IIS:/'
            - location: 'site0'
            - settings:
              system.webServer/security/authentication/basicAuthentication:
                enabled: True

    '''

    ret = {'name': name,
           'changes': {},
           'comment': str(),
           'result': None}

    if not settings:
        ret['comment'] = 'No settings to change provided.'
        ret['result'] = True
        return ret

    ret_settings = {
        'changes': {},
        'failures': {},
    }

    settings_list = list()

    for filter, filter_settings in settings.items():
        for setting_name, value in filter_settings.items():
            settings_list.append({'filter': filter, 'name': setting_name, 'value': value})

    current_settings_list = __salt__['win_iis.get_webconfiguration_settings'](name=name,
                                                                                  settings=settings_list, location=location)
    for idx, setting in enumerate(settings_list):

        is_collection = setting['name'].split('.')[-1] == 'Collection'

        if ((is_collection and list(map(dict, setting['value'])) != list(map(dict, current_settings_list[idx]['value'])))
                or (not is_collection and str(setting['value']) != str(current_settings_list[idx]['value']))):
            ret_settings['changes'][setting['filter'] + '.' + setting['name']] = {'old': current_settings_list[idx]['value'],
                                                                                  'new': settings_list[idx]['value']}
    if not ret_settings['changes']:
        ret['comment'] = 'Settings already contain the provided values.'
        ret['result'] = True
        return ret
    elif __opts__['test']:
        ret['comment'] = 'Settings will be changed.'
        ret['changes'] = ret_settings
        return ret

    __salt__['win_iis.set_webconfiguration_settings'](name=name, settings=settings_list, location=location)

    new_settings_list = __salt__['win_iis.get_webconfiguration_settings'](name=name,
                                                                              settings=settings_list, location=location)
    for idx, setting in enumerate(settings_list):

        is_collection = setting['name'].split('.')[-1] == 'Collection'

        if ((is_collection and setting['value'] != new_settings_list[idx]['value'])
                or (not is_collection and str(setting['value']) != str(new_settings_list[idx]['value']))):
            ret_settings['failures'][setting['filter'] + '.' + setting['name']] = {'old': current_settings_list[idx]['value'],
                                                                                   'new': new_settings_list[idx]['value']}
            ret_settings['changes'].pop(setting['filter'] + '.' + setting['name'], None)

    if ret_settings['failures']:
        ret['comment'] = 'Some settings failed to change.'
        ret['changes'] = ret_settings
        ret['result'] = False
    else:
        ret['comment'] = 'Set settings to contain the provided values.'
        ret['changes'] = ret_settings['changes']
        ret['result'] = True

    return ret