# Buggy code
def compare_rules(connection, module, current_listeners, listener):
    """
    Compare rules and return rules to add, rules to modify and rules to remove
    Rules are compared based on priority

    :param connection:
    :param module:
    :param current_listeners:
    :param listener:
    :return:
    """

    # Run through listeners looking for a match (by port) to get the ARN
    for current_listener in current_listeners:
        if current_listener["Port"] == listener["Port"]:
            listener["ListenerArn"] = current_listener["ListenerArn"]
            break

    # Get rules for the listener
    current_rules = get_listener_rules(connection, module, listener["ListenerArn"])

    rules_to_modify = []
    rules_to_delete = []

    for current_rule in current_rules:
        current_rule_passed_to_module = False
        for new_rule in listener["Rules"][:]:
            if current_rule["Priority"] == new_rule["Priority"]:
                current_rule_passed_to_module = True
                # Remove what we match so that what is left can be marked as 'to be added'
                listener["Rules"].remove(new_rule)
                modified_rule = compare_rule(current_rule, new_rule)
                if modified_rule:
                    modified_rule["Priority"] = int(current_rule["Priority"])
                    modified_rule["RuleArn"] = current_rule["RuleArn"]
                    modified_rule["Actions"] = current_rule["Actions"]
                    modified_rule["Conditions"] = current_rule["Conditions"]
                    rules_to_modify.append(modified_rule)
                break

        # If the current rule was not matched against passed rules, mark for removal
        if not current_rule_passed_to_module and not current_rule["IsDefault"]:
            rules_to_delete.append(current_rule["RuleArn"])

    rules_to_add = listener["Rules"]

    return rules_to_add, rules_to_modify, rules_to_delete


# Traceback (ParamValidationError)
Unknown parameter in input: "Rules", must be one of: LoadBalancerArn, Protocol, Port, SslPolicy, Certificates, DefaultActions
fatal: [localhost]: FAILED! => {"changed": false, "failed": true, "module_stderr": "Traceback (most recent call last):\n  File \"/tmp/ansible_LtFMN2/ansible_module_elb_application_lb.py\", line 1011, in <module>\n    main()\n  File \"/tmp/ans
ible_LtFMN2/ansible_module_elb_application_lb.py\", line 1006, in main\n    create_or_update_elb(connection, connection_ec2, module)\n  File \"/tmp/ansible_LtFMN2/ansible_module_elb_application_lb.py\", line 901, in create_or_update_elb\n
listener_changed = create_or_update_elb_listeners(connection, module, elb)\n  File \"/tmp/ansible_LtFMN2/ansible_module_elb_application_lb.py\", line 722, in create_or_update_elb_listeners\n    connection.create_listener(**listener_to_add)\n
File \"/usr/local/lib/python2.7/dist-packages/botocore/client.py\", line 310, in _api_call\n    return self._make_api_call(operation_name, kwargs)\n  File \"/usr/local/lib/python2.7/dist-packages/botocore/client.py\", line 573, in _make_api_
call\n    api_params, operation_model, context=request_context)\n  File \"/usr/local/lib/python2.7/dist-packages/botocore/client.py\", line 628, in _convert_to_request_dict\n    api_params, operation_model)\n  File \"/usr/local/lib/python2.7/
dist-packages/botocore/validate.py\", line 291, in serialize_to_request\n    raise ParamValidationError(report=report.generate_report())\nbotocore.exceptions.ParamValidationError: Parameter validation failed:\nUnknown parameter in input: \"Ru
les\", must be one of: LoadBalancerArn, Protocol, Port, SslPolicy, Certificates, DefaultActions\n", "module_stdout": "", "msg": "MODULE FAILURE", "rc": 0}

# Fixed code
def compare_rules(connection, module, current_listeners, listener):
    """
    Compare rules and return rules to add, rules to modify and rules to remove
    Rules are compared based on priority

    :param connection:
    :param module:
    :param current_listeners:
    :param listener:
    :return:
    """

    # Run through listeners looking for a match (by port) to get the ARN
    for current_listener in current_listeners:
        if current_listener["Port"] == listener["Port"]:
            listener["ListenerArn"] = current_listener["ListenerArn"]
            break

    # Get rules for the listener
    current_rules = get_listener_rules(connection, module, listener["ListenerArn"])

    rules_to_modify = []
    rules_to_delete = []

    for current_rule in current_rules:
        current_rule_passed_to_module = False
        for new_rule in listener["Rules"][:]:
            if current_rule["Priority"] == new_rule["Priority"]:
                current_rule_passed_to_module = True
                # Remove what we match so that what is left can be marked as 'to be added'
                listener["Rules"].remove(new_rule)
                modified_rule = compare_rule(current_rule, new_rule)
                if modified_rule:
                    modified_rule["Priority"] = int(current_rule["Priority"])
                    modified_rule["RuleArn"] = current_rule["RuleArn"]
                    modified_rule["Actions"] = new_rule["Actions"]
                    modified_rule["Conditions"] = new_rule["Conditions"]
                    rules_to_modify.append(modified_rule)
                break

        # If the current rule was not matched against passed rules, mark for removal
        if not current_rule_passed_to_module and not current_rule["IsDefault"]:
            rules_to_delete.append(current_rule["RuleArn"])

    rules_to_add = listener["Rules"]

    return rules_to_add, rules_to_modify, rules_to_delete