/**
 * Rules Interface Scripts
 */

jQuery(document).ready(function() {

    'use strict';

    /**
     * Track duplicate actions
     */
    var duplicate_running = false;

    /**
     * Define rule editor elements
     */
    var rp_wcdpd_elements = {
        product_pricing: {
            children: {
                product_condition: {},
                bogo_product_condition: {},
                condition: {},
                quantity_range: {},
                group_product: {}
            }
        },
        cart_discounts: {
            children: {
                product_condition: {},
                condition: {}
            }
        },
        checkout_fees: {
            children: {
                product_condition: {},
                condition: {}
            }
        }
    };

    /**
     * Send serialized copy of data on submit in case we hit the max_input_vars limit
     */
    jQuery('form').has('.rp_wcdpd_settings').last().on('submit', function(e) {
        var form_data = jQuery(this).serialize();
        jQuery(this).find('input[name="rp_wcdpd_settings_serialized"]').remove();
        jQuery(this).prepend('<input type="hidden" name="rp_wcdpd_settings_serialized" />');
        jQuery(this).find('input[name="rp_wcdpd_settings_serialized"]').val(form_data);
        return true;
    });

    /**
     * Set up row state color coding
     */
    function set_up_row_state_color_coding(row)
    {

        // Rule selection method
        jQuery('.rp_wcdpd_settings select.rp_wcdpd_rule_selection_method').on('change', function() {
            update_row_state_color_coding(row);
        });

        // Rule exclusivity
        row.find('.rp_wcdpd_field_exclusivity').on('change', function() {
            update_row_state_color_coding(row);
        });

        // Trigger now
        update_row_state_color_coding(row);
    }

    /**
     * Update row state color coding
     */
    function update_row_state_color_coding(row)
    {

        // Reference row handle
        var handle = row.find('.rp_wcdpd_accordion_handle').first();

        // Reference inputs
        var rule_selection_method_value = jQuery('.rp_wcdpd_settings select.rp_wcdpd_rule_selection_method').val();
        var rule_exclusivity_value      = row.find('.rp_wcdpd_field_exclusivity').first().val();

        // Row disabled or all fields disabled
        if (rule_exclusivity_value === 'disabled' || rule_selection_method_value === 'disabled') {
            handle.css('border-left-color', '#cf4944');
        }
        // Row enabled
        else {
            handle.css('border-left-color', '#118238');
        }
    }

    /**
     * Iterate over elements and set up view
     */
    if (typeof rp_wcdpd_config === 'object') {
        jQuery.each(rp_wcdpd_elements, function(key, children) {

            // Set up all rules
            jQuery('#rp_wcdpd_' + key).each(function() {

                // Get config
                var config = jQuery.rightpress.object_key_check(rp_wcdpd_config, key) ? rp_wcdpd_config[key] : [];

                // Set up row
                set_up_parent(jQuery(this), key, config);
            });
        });
    }

    /**
     * Set up parent element
     */
    function set_up_parent(container, key, config)
    {

        // No rows configured yet?
        if (config.length === 0) {
            add_no_rows_notice(container, key);
        }
        // At least one row exists
        else {

            // Iterate over list of rows and add them
            jQuery.each(config, function(index, row_config) {
                add_row(key, row_config);
            });

            // Refresh accordion
            refresh_accordion(key);
        }

        // Render add row button
        append(container, 'add_row')

        // Bind click action
        jQuery('#rp_wcdpd_add_row button').on('click', function() {
            jQuery(this).prop('disabled', true);
            add_row(key, false);
            refresh_accordion(key);
            jQuery(this).prop('disabled', false);
        });
    }

    /**
     * Add no rows notice
     */
    function add_no_rows_notice(selector, key)
    {
        prepend(selector, 'no_rows');
    }

    /**
     * Remove no rows notice
     */
    function remove_no_rows_notice(key)
    {
        jQuery('#rp_wcdpd_' + key + ' #rp_wcdpd_no_rows').remove();
    }

    /**
     * Add wrapper
     */
    function add_wrapper(key)
    {

        // Make sure we don't have one yet before proceeding
        if (jQuery('#rp_wcdpd_' + key + ' #rp_wcdpd_rule_wrapper').length === 0) {

            // Add wrapper
            prepend('#rp_wcdpd_' + key, 'rule_wrapper', null);

            // Reference form
            var form = jQuery('#rp_wcdpd_' + key + ' #rp_wcdpd_rule_wrapper').closest('form');

            // Make it sortable accordion
            jQuery('#rp_wcdpd_' + key + ' #rp_wcdpd_rule_wrapper').accordion({
                header: '> div > div.rp_wcdpd_accordion_handle',
                icons: false,
                collapsible: true,
                heightStyle: 'content',
                active: false,
                beforeActivate: function(event, ui) {
                    panel_activating(key, event, ui);
                }
            }).sortable({
                handle: '.rp_wcdpd_row_sort_handle',
                axis:   'y',
                stop: function(event, ui) {
                    fix_rows(key);
                }
            });
        }
    }

    /**
     * Remove wrapper
     */
    function remove_wrapper(key)
    {
        jQuery('#rp_wcdpd_' + key + ' #rp_wcdpd_rule_wrapper').remove();
    }

    /**
     * Handle panel activation
     */
    function panel_activating(key, event, ui)
    {

        // Check if panel needs rendering
        if (ui.newPanel.has('.rp_wcdpd_loading_data').length) {

            // Select row
            var row = ui.newPanel.closest('.rp_wcdpd_row');

            // Add row content
            add_row_content(key, row);
        }
    }

    /**
     * Add one row
     */
    function add_row(key, config)
    {

        var selector = '#rp_wcdpd_' + key + ' #rp_wcdpd_rule_wrapper';

        // Add wrapper
        add_wrapper(key);

        // Make sure we don't have the "Nothing to display" notice
        remove_no_rows_notice(key);

        // Add row element
        append(selector, 'row', null);

        // Select current row
        var row = jQuery(selector).children().last();
        var row_key = jQuery(selector).children().length - 1;

        // Set initial config data
        row.data('rp_wcdpd_initial_config', config);

        // Fix identifiers, values and visibility
        fix_rows(key);
        fix_parent_values(key, row, row_key, config);

        // Fix row headers
        fix_row_header(row, key, config);

        // Add duplicate event handler
        add_duplicate_event_handler(key, row);

        // Handle delete action
        jQuery('#rp_wcdpd_' + key + ' .rp_wcdpd_row_remove_handle').last().on('click', function() {
            remove_row(key, jQuery(this).closest('.rp_wcdpd_row'));
        });

        // Exclude field in header from activating panel change
        row.find('.rp_wcdpd_field_exclusivity').on('click', function() {
            event.stopPropagation();
            return false;
        });

        // Set up row state color coding
        set_up_row_state_color_coding(row);
    }

    /**
     * Add row content
     */
    function add_row_content(key, row)
    {

        // Get row key
        var row_key = row.index();

        // Get initial config
        var config = typeof row.data('rp_wcdpd_initial_config') !== 'undefined' ? row.data('rp_wcdpd_initial_config') : false;

        // Do not override potentially new exclusivity setting
        if (config) {
            if (typeof config.exclusivity !== 'undefined' && row.find('#rp_wcdpd_' + key + '_exclusivity_' + row_key).length) {

                // Get value front field
                var exclusivity_value = row.find('#rp_wcdpd_' + key + '_exclusivity_' + row_key).val();

                // Values do not match - use one from field
                if (config.exclusivity !== exclusivity_value) {
                    config.exclusivity = exclusivity_value;
                }
            }
        }

        // Add template content
        row.find('.rp_wcdpd_row_content').html(get_template('row_content'));

        // Set up child elements
        jQuery.each(rp_wcdpd_elements[key].children, function(type) {
            set_up(key, type + 's', row, row_key, config);
        });

        // Fix field identifiers
        fix_rows(key);

        // Fix field values
        fix_parent_values(key, row, row_key, config);

        // Display correct settings area for product pricing rules
        if (key === 'product_pricing') {
            row.find('.rp_wcdpd_product_pricing_field_method').last().on('change', function () {
                toggle_product_pricing_settings(jQuery(this), key);
            });
            toggle_product_pricing_settings(row.find('.rp_wcdpd_product_pricing_field_method').last(), key);
        }
        // Show or hide cart item settings for cart discount and checkout fee rules
        else {
            row.find('.rp_wcdpd_' + key + '_field_pricing_method').on('change', function() {
                toggle_cart_item_settings(jQuery(this), key);
            });
            toggle_cart_item_settings(row.find('.rp_wcdpd_' + key + '_field_pricing_method'), key);
            fix_row_header(row, key, false);
        }

        // Initial condition fix
        jQuery.each(['bogo_product_condition', 'product_condition', 'condition'], function(index, alias) {

            // Condition identifier
            var j = 0;

            // Iterate over conditions
            row.find('.rp_wcdpd_' + alias).each(function() {

                var condition = jQuery(this);
                var skip_condition = false;

                // Condition is disabled or no longer exists
                jQuery.each(['_disabled', '_disabled_taxonomy', '_non_existent', '_non_existent_taxonomy'], function(flag_index, flag_type) {
                    if (typeof config[alias + 's'][j][flag_type] !== 'undefined') {
                        condition.find('.rp_wcdpd_condition_content, .rp_wcdpd_product_condition_content').html(get_template('condition' + flag_type));
                        skip_condition = true;
                    }
                });

                // Skip to next condition as current one is disabled
                if (skip_condition) {
                    j++;
                    return true;
                }

                // Fields
                fix_condition(key, alias, jQuery(this));

                // Field identifiers
                fix_child_element(key, (alias + 's'), jQuery(this), row_key, j);

                // Field values
                fix_child_values(key, alias, row, row_key, jQuery(this), j, config);

                // Fix meta and coupon conditions (correct values were not present when it was first run)
                toggle_condition_fields(key, alias, jQuery(this), jQuery(this).find('.rp_wcdpd_' + key + '_' + alias + '_type').val());

                // Increment condition identifier
                j++;
            });
        });

        // Initial group product fix
        var j = 0;

        row.find('.rp_wcdpd_group_product').each(function() {

            var group_product = jQuery(this);
            var skip_group_product = false;

            // Group product condition  is disabled or no longer exists
            jQuery.each(['_disabled', '_disabled_taxonomy', '_non_existent', '_non_existent_taxonomy'], function(flag_index, flag_type) {
                if (typeof config['group_products'][j][flag_type] !== 'undefined') {
                    group_product.find('.rp_wcdpd_group_product_content').html(get_template('condition' + flag_type));
                    skip_group_product = true;
                }
            });

            // Skip to next group product condition as current one is disabled
            if (skip_group_product) {
                j++;
                return true;
            }

            // Fix group product
            fix_group_product(key, jQuery(this));

            // Increment group product condition identifier
            j++;
        });

        // Set up header update
        var selectors = [];

        jQuery.each(['title', 'note', 'pricing_method', 'pricing_value', 'group_pricing_method', 'group_pricing_value', 'bogo_pricing_method', 'bogo_pricing_value', 'bogo_purchase_quantity', 'bogo_receive_quantity'], function(index, selector) {
            selectors.push('#rp_wcdpd_' + key + '_' + selector + '_' + row_key);
        });

        jQuery('body').on('keyup change', selectors.join(), null, function() {
            fix_row_header(jQuery(this), key, false);
        });

        // Focus on first important field
        if (config === false) {
            var focus_selector = (key === 'product_pricing' ? '.rp_wcdpd_product_pricing_field_note' : '.rp_wcdpd_' + key + '_field_title');
            row.find(focus_selector).focus();
        }
    }

    /**
     * Add duplicate event handler
     */
    function add_duplicate_event_handler(key, row)
    {
        row.find('.rp_wcdpd_row_duplicate_handle').on('click', function() {

            // Prevent accordion from opening/closing
            event.stopPropagation();

            // Prevent multiple clicks
            if (duplicate_running) {
                return;
            }
            duplicate_running = true;

            // Duplicate row
            duplicate_row(key, jQuery(this).closest('.rp_wcdpd_row'));

            // Prevent multiple clicks
            setTimeout(function(){
                duplicate_running = false;
            }, 1000);
        });
    }

    /**
     * Remove duplicate event handler
     */
    function remove_duplicate_event_handler(key, row)
    {
        row.find('.rp_wcdpd_row_duplicate_handle').off('click');
    }

    /**
     * Duplicate one row
     */
    function duplicate_row(key, row)
    {

        // Select wrapper
        var wrapper = row.closest('#rp_wcdpd_rule_wrapper');

        // Add row content if not added yet
        if (row.find('.rp_wcdpd_' + key + '_unchanged').length) {
            add_row_content(key, row);
        }

        // Get original row and row key
        var original_row = row;
        var original_row_key = row.index();

        // Get new row key
        var row_key = wrapper.children().length;

        // Start config mockup
        var config = {};
        var multiselect_options = {};

        // Iterate over all form elements and add values to config mockup
        original_row.find('input, select').each(function() {

            // Skip hidden fields
            if (jQuery(this).is(':disabled') || jQuery(this).attr('type') === 'hidden') {
                return;
            }

            // Get name parts
            var name_parts = jQuery(this).prop('name').replace('rp_wcdpd_settings[' + key + '][' + original_row_key + ']', '').replace('[]', '').slice(1, -1).split('][');

            // Add value to config mockup object
            jQuery.rightpress.add_nested_object_value(config, name_parts, jQuery(this).val());

            // Get multiselect field options
            if (jQuery.rightpress.field_is_multiselect(jQuery(this))) {
                var current_options = [];

                jQuery(this).find('option').each(function() {
                    current_options.push({
                        id: jQuery(this).prop('value'),
                        text: jQuery(this).text()
                    });
                });

                if (current_options.length > 0) {
                    name_parts[0] = name_parts[0] + '_multiselect_option_labels';
                    jQuery.rightpress.add_nested_object_value(config, name_parts, current_options);
                }
            }
        });

        // Add new row
        add_row(key, config);

        // Refresh accordion
        refresh_accordion(key);
    }

    /**
     * Remove one row
     */
    function remove_row(key, row)
    {
        // Last row? Remove the entire wrapper and add "Nothing to display"
        if (row.closest('#rp_wcdpd_rule_wrapper').children().length < 2) {
            remove_wrapper(key);
            add_no_rows_notice('#rp_wcdpd_' + key, key)
        }

        // Remove single row and fix ids
        else {
            row.remove();
            fix_rows(key);
        }
    }

    /**
     * Fix attributes
     */
    function fix_rows(key)
    {
        var i = 0;  // Row identifier
        var j = 0;  // Child element identifier, e.g. conditions within a give row

        // Iterate over rows
        jQuery('#rp_wcdpd_' + key + ' #rp_wcdpd_rule_wrapper .rp_wcdpd_row').each(function() {

            var row = jQuery(this);
            var element_wrappers = [];

            // Fix conditions etc
            jQuery.each(rp_wcdpd_elements[key].children, function(type) {

                var type_plural = type + 's';

                // Check if we have elements of this type for this row and handle them
                row.find('.rp_wcdpd_row_content_' + type_plural + '_row').each(function() {

                    element_wrappers.push(jQuery(this));

                    // Iterate over elements of this type of current row
                    jQuery(this).find('.rp_wcdpd_' + type + '_wrapper .rp_wcdpd_' + type).each(function() {

                        // Fix child element
                        fix_child_element(key, type_plural, jQuery(this), i, j);

                        // Increment element identifier
                        j++;
                    });

                    // Reset element identifier
                    j = 0;
                });
            });

            // Iterate over all field elements of this element
            jQuery(this).find('input, select, label').each(function() {

                var current_form_element = jQuery(this);

                // Do not touch child elements (already sorted above)
                if (element_wrappers.length > 0) {

                    var proceed = true;

                    jQuery.each(element_wrappers, function(index, value) {
                        if (jQuery.contains(value[0], current_form_element[0])) {
                            proceed = false;
                            return true;
                        }
                    });

                    if (!proceed) {
                        return true;
                    }
                }

                // Attribute id
                if (typeof jQuery(this).prop('id') !== 'undefined' && jQuery(this).prop('id')) {
                    var new_value = jQuery(this).prop('id').replace(/(\{i\}|\d+)?$/, i);
                    jQuery(this).prop('id', new_value);
                }

                // Attribute name
                if (typeof jQuery(this).prop('name') !== 'undefined') {
                    var new_value = jQuery(this).prop('name').replace(new RegExp('rp_wcdpd_settings\\[' + key + '\\]\\[(\\{i\\}|\\d+)\\]?'), 'rp_wcdpd_settings[' + key + '][' + i + ']');
                    jQuery(this).prop('name', new_value);
                }

                // Attribute for
                if (typeof jQuery(this).prop('for') !== 'undefined' && jQuery(this).prop('for').length) {
                    var new_value = jQuery(this).prop('for').replace(/(\{i\}|\d+)?$/, i);
                    jQuery(this).prop('for', new_value);
                }
            });

            // Increment row identifier
            i++;
        });
    }

    /**
     * Fix child element identifiers
     */
    function fix_child_element(key, type_plural, element, i, j)
    {
        // Iterate over all field elements of current element
        element.find('input, select').each(function() {

            // Attribute id
            if (typeof jQuery(this).prop('id') !== 'undefined') {
                var new_value = jQuery(this).prop('id').replace(/_(\{i\}|\d+)?_/, '_' + i + '_').replace(/(\{j\}|\d+)?$/, j);
                jQuery(this).prop('id', new_value);
            }

            // Attribute name
            if (typeof jQuery(this).prop('name') !== 'undefined') {
                var new_value = jQuery(this).prop('name').replace(new RegExp('rp_wcdpd_settings\\[' + key + '\\]\\[(\\{i\\}|\\d+)\\]?'), 'rp_wcdpd_settings[' + key + '][' + i + ']').replace(new RegExp('\\[' + type_plural + '\\]\\[(\\{j\\}|\\d+)\\]?'), '[' + type_plural + '][' + j + ']');
                jQuery(this).prop('name', new_value);
            }
        });
    }

    /**
     * Fix parent field values
     */
    function fix_parent_values(key, row, row_key, config)
    {

        // Row identifier
        var i = typeof row_key !== 'undefined' ? row_key : 0;

        // Get rows to fix values for
        var rows = typeof row !== 'undefined' ? [row] : jQuery('#rp_wcdpd_' + key + ' #rp_wcdpd_rule_wrapper .rp_wcdpd_row');

        // Iterate over rows
        jQuery.each(rows, function() {

            var row = jQuery(this);

            // Iterate over all field elements of this row except child elements
            jQuery(this).find('input:not(.rp_wcdpd_child_element_field), select:not(.rp_wcdpd_child_element_field)').each(function() {

                // Skip "unchanged" flag field
                if (jQuery(this).hasClass('rp_wcdpd_' + key + '_unchanged')) {
                    return;
                }

                // Get field key
                var field_key = jQuery(this).prop('id').replace(new RegExp('^rp_wcdpd_' + key + '_'), '').replace(/(_\d+)?$/, '');

                // Select options in select fields
                if (jQuery(this).is('select')) {
                    if (config !== false && jQuery.rightpress.object_key_check(config, field_key) && config[field_key]) {
                        if (jQuery.rightpress.field_is_multiselect(jQuery(this))) {

                            if (jQuery.rightpress.object_key_check(config, (field_key + '_multiselect_option_labels')) && typeof config[(field_key + '_multiselect_option_labels')] === 'object') {
                                for (var k = 0; k < config[field_key].length; k++) {
                                    var all_options = config[(field_key + '_multiselect_option_labels')];
                                    var current_option_key = config[field_key][k];

                                    for (var l = 0; l < all_options.length; l++) {
                                        if (jQuery.rightpress.object_key_check(all_options, l, 'id') && all_options[l]['id'] == current_option_key) {
                                            var current_option_label = all_options[l]['text'];
                                            jQuery(this).append(jQuery('<option></option>').attr('value', current_option_key).prop('selected', true).text(current_option_label));
                                        }
                                    }
                                }
                            }
                        }
                        else {
                            jQuery(this).val(config[field_key]);
                        }
                    }
                }

                // Add value for text input fields
                else if (jQuery(this).is('input')) {
                    if (config !== false && jQuery.rightpress.object_key_check(config, field_key)) {
                        jQuery(this).prop('value', config[field_key]);
                    }
                    else {
                        jQuery(this).removeAttr('value');
                    }
                }

                // Initialize Select2 multiselect
                if (jQuery(this).hasClass('rp_wcdpd_select2_multiselect') && !jQuery(this).data('select2')) {
                    initialize_select2_multiselect(key, jQuery(this));
                }

                // Initialize Select2 grouped
                if (jQuery(this).hasClass('rp_wcdpd_select2_grouped') && !jQuery(this).data('select2')) {
                    jQuery(this).rightpress_grouped_select2();
                }
            });

            // Fix child values
            jQuery.each(rp_wcdpd_elements[key].children, function(type) {
                fix_child_values(key, type, row, i, null, null, config);
            });

            // Increment row identifier
            i++;
        });
    }

    /**
     * Set up child elements, e.g. conditions for one row
     */
    function set_up(key, type, row, row_key, config)
    {

        var type_singular = type.replace(/s$/, '');

        // No existing children of given type
        if (config === false || typeof config !== 'object' || config.length < 1 || typeof config[type] !== 'object' || config[type].length < 1) {
            add_no(key, type, row);
        }
        // Set up existing children of given type
        else {

            jQuery.each(config[type], function(index, child_config) {
                add(key, type_singular, row, row_key, config);
            });
        }

        // Bind click action
        row.find('.rp_wcdpd_add_' + type_singular + ' button').on('click', function() {
            jQuery(this).prop('disabled', true);
            add(key, type_singular, row, row_key, false);
            jQuery(this).prop('disabled', false);
        });
    }

    /**
     * Add no child elements (e.g. conditions) notice
     */
    function add_no(key, type, row)
    {
        if (!row.find('.rp_wcdpd_row_content_' + type + '_row .rp_wcdpd_inner_wrapper .rp_wcdpd_no_' + type).length) {
            prepend(row.find('.rp_wcdpd_row_content_' + type + '_row .rp_wcdpd_inner_wrapper'), 'no_' + type);
        }
    }

    /**
     * Remove no child elements (e.g. conditions) notice
     */
    function remove_no(key, type, row)
    {
        row.find('.rp_wcdpd_no_' + type).remove();
    }

    /**
     * Add one child element, e.g. condition
     */
    function add(key, type, row, row_key, config)
    {

        // Add wrapper
        add_child_wrapper(key, type, row);

        // Make sure we don't have the no child elements notice
        remove_no(key, type + 's', row);

        // Add element
        append(row.find('.rp_wcdpd_' + type + '_wrapper'), type, null);

        // Select current row
        var child_row = row.find('.rp_wcdpd_' + type).last();
        var child_row_key = row.find('.rp_wcdpd_' + type).length - 1;

        // Fix identifiers, values and visibility on newly added item
        if (config === false) {

            // Fix fields
            fix_rows(key);
            fix_child_values(key, type, row, row_key, child_row, child_row_key, config);

            // Fix condition
            jQuery.each(['bogo_product_condition', 'product_condition', 'condition'], function(index, alias) {

                if (type === alias) {

                    // Fix condition fields
                    fix_condition(key, alias, child_row);

                    // Fix condition field identifiers
                    fix_child_element(key, (alias + 's'), child_row, row_key, child_row_key);

                    // Fix condition field values
                    fix_child_values(key, alias, row, row_key, child_row, child_row_key, config);
                }
            });

            // Other specific fixes by type
            if (type === 'group_product') {
                fix_group_product(key, child_row);
            }
            else if (type === 'quantity_range') {
                toggle_volume_pricing_methods(child_row, key);
            }
        }

        // Handle delete action
        row.find('.rp_wcdpd_' + type + '_remove_handle').last().on('click', function() {
            remove(key, type, jQuery(this).closest('.rp_wcdpd_' + type));
        });

        // Focus on first important field
        if (config === false) {

            var focus_selector = null;

            if (type === 'condition') {
                // May be distracting, disabled
                // focus_selector = '.rp_wcdpd_' + key + '_condition_date:enabled';
            }
            else if (type === 'product_condition') {
                focus_selector = '.rp_wcdpd_' + key + '_product_condition_products:enabled';
            }
            else if (type === 'bogo_product_condition') {
                focus_selector = '.rp_wcdpd_' + key + '_bogo_product_condition_products:enabled';
            }
            else if (type === 'quantity_range') {
                focus_selector = '.rp_wcdpd_' + key + '_quantity_range_from:enabled';
            }
            else if (type === 'group_product') {
                focus_selector = '.rp_wcdpd_' + key + '_group_product_quantity:enabled';
            }

            if (focus_selector !== null) {
                child_row.find(focus_selector).focus();
            }
        }
    }

    /**
     * Remove one child element, e.g. condition
     */
    function remove(key, type, element)
    {
        var row = element.closest('.rp_wcdpd_row');

        // Last element? Remove the entire wrapper and add no child elements notice
        if (row.find('.rp_wcdpd_' + type + '_wrapper').children().length < 2) {
            remove_child_wrapper(key, type, row);
            add_no(key, type + 's', row);
        }

        // Remove single element and fix ids
        else {
            element.remove();
            fix_rows(key);
        }
    }

    /**
     * Fix child field values
     */
    function fix_child_values(key, type, row, row_key, child_row, child_row_key, config)
    {

        var type_plural = type + 's';

        // Row identifiers
        var i = row_key;
        var j = typeof child_row_key !== 'undefined' && child_row_key !== null ? child_row_key : 0;

        // Get rows to fix values for
        var rows = typeof child_row !== 'undefined' && child_row !== null ? [child_row] : row.find('.rp_wcdpd_' + type + '_wrapper .rp_wcdpd_' + type);

        // Iterate over child rows
        jQuery.each(rows, function() {

            // Iterate over all field elements of current element
            jQuery(this).find('input, select').each(function() {

                // Get field key
                var field_key = jQuery(this).prop('id').replace(new RegExp('^rp_wcdpd_' + key + '_' + type_plural + '_'), '').replace(/^(\d+_)?/, '').replace(/(_\d+)?$/, '');

                // Select options in select fields
                if (jQuery(this).is('select')) {
                    if (config !== false && jQuery.rightpress.object_key_check(config, type_plural, j, field_key) && config[type_plural][j][field_key]) {
                        if (jQuery.rightpress.field_is_multiselect(jQuery(this))) {

                            if (jQuery.rightpress.object_key_check(config, (type_plural + '_multiselect_option_labels'), j) && typeof config[(type_plural + '_multiselect_option_labels')][j][field_key] === 'object') {

                                var all_options = config[(type_plural + '_multiselect_option_labels')][j][field_key];
                                var multiselect_options_html = '';

                                for (var k = 0; k < config[type_plural][j][field_key].length; k++) {

                                    var current_option_key = config[type_plural][j][field_key][k];

                                    for (var l = 0; l < all_options.length; l++) {
                                        if (jQuery.rightpress.object_key_check(all_options, l, 'id') && all_options[l]['id'] == current_option_key) {
                                            multiselect_options_html += '<option value="' + current_option_key + '" selected="selected">' + all_options[l]['text'] + '</option>';
                                        }
                                    }
                                }

                                if (multiselect_options_html !== '') {
                                    jQuery(this).append(multiselect_options_html);
                                }
                            }
                        }
                        else {
                            jQuery(this).val(config[type_plural][j][field_key]);
                        }
                    }
                }

                // Add value for text input fields
                else if (typeof jQuery(this).prop('value') !== 'undefined' /*&& jQuery(this).prop('value') === '{value}'*/) {
                    if (config !== false && jQuery.rightpress.object_key_check(config, type_plural, j, field_key)) {
                        jQuery(this).prop('value', config[type_plural][j][field_key]);
                    }
                    else {
                        jQuery(this).removeAttr('value');
                    }
                }

                // Select2 setup
                if (!jQuery(this).data('select2')) {

                    // Multiselect
                    if (jQuery(this).hasClass('rp_wcdpd_select2_multiselect')) {
                        initialize_select2_multiselect(key, jQuery(this), type);
                    }
                    // Grouped
                    else if (jQuery(this).hasClass('rp_wcdpd_select2_grouped')) {
                        jQuery(this).rightpress_grouped_select2();
                    }
                }
            });

            // Increment element identifier
            j++;
        });
    }

    /**
     * Add wrapper for child elements, e.g. conditions
     */
    function add_child_wrapper(key, type, row)
    {
        // Make sure we don't have one yet before proceeding
        if (row.find('.rp_wcdpd_' + type + '_wrapper').length === 0) {

            // Add wrapper
            prepend(row.find('.rp_wcdpd_row_content_' + type + 's_row .rp_wcdpd_inner_wrapper'), type + '_wrapper', null);

            // Make it sortable
            row.find('.rp_wcdpd_' + type + '_wrapper').sortable({
                axis:       'y',
                handle:     '.rp_wcdpd_' + type + '_sort_handle',
                opacity:    0.7,
                stop: function(event, ui) {

                    // Remove styles added by jQuery UI
                    jQuery(this).find('.rp_wcdpd_' + type).each(function() {
                        jQuery(this).removeAttr('style');
                    });

                    // Fix ids, names etc
                    fix_rows(key);
                }
            });
        }
    }

    /**
     * Remove child element wrapper
     */
    function remove_child_wrapper(key, type, row)
    {
        row.find('.rp_wcdpd_' + type + '_wrapper').remove();
    }

    /**
     * Fix condition
     */
    function fix_condition(key, alias, element)
    {
        // Get current condition type
        var condition_type = element.find('.rp_wcdpd_' + key + '_' + alias + '_type').val();

        // Condition type
        element.find('.rp_wcdpd_' + key + '_' + alias + '_type').on('change', function() {
            condition_type = element.find('.rp_wcdpd_' + key + '_' + alias + '_type').val();
            toggle_condition_fields(key, alias, element, condition_type);
        });
        toggle_condition_fields(key, alias, element, condition_type);
    }

    /**
     * Toggle visibility of condition fields
     */
    function toggle_condition_fields(key, alias, element, condition_type)
    {
        // Reference wrapper and row
        var wrapper = element.find('.rp_wcdpd_' + alias + '_setting_fields_wrapper');
        var row = element.closest('.rp_wcdpd_row');

        // Make sure we don't have required set of fields yet
        if (!wrapper.find('.rp_wcdpd_' + alias + '_setting_fields_' + condition_type).length) {

            // Clear wrapper
            wrapper.html('');

            // Add condition fields
            append(wrapper, (alias + '_setting_fields_' + condition_type), null);

            // Field identifiers
            fix_child_element(key, (alias + 's'), element, row.index(), element.index());

            // Field values
            fix_child_values(key, alias, row, row.index(), element, element.index(), false)

            // Fix meta field condition
            element.find('.rp_wcdpd_' + key + '_' + alias + '_method').on('change', function() {
                condition_type = element.find('.rp_wcdpd_' + key + '_' + alias + '_type').val();
                fix_meta_field_condition(key, alias, element, condition_type);
            });

            // Fix coupons applied condition
            element.find('.rp_wcdpd_' + key + '_' + alias + '_method').on('change', function() {
                condition_type = element.find('.rp_wcdpd_' + key + '_' + alias + '_type').val();
                fix_coupons_applied_condition(key, alias, element, condition_type);
            });

            // Date and time pickers
            element.find('.rp_wcdpd_date').datetimepicker(rp_wcdpd_datetimepicker_date_config.x);
            element.find('.rp_wcdpd_time').datetimepicker(rp_wcdpd_datetimepicker_time_config.x);
            element.find('.rp_wcdpd_datetime').datetimepicker(rp_wcdpd_datetimepicker_datetime_config.x);
            jQuery.datetimepicker.setLocale(rp_wcdpd_datetimepicker_locale.x);
        }

        // Fix meta field condition
        fix_meta_field_condition(key, alias, element, condition_type);

        // Fix coupons applied condition
        fix_coupons_applied_condition(key, alias, element, condition_type);
    }

    /**
     * Fix fields of meta field condition
     */
    function fix_meta_field_condition(key, alias, element, condition_type)
    {
        // Only proceed if condition type is meta field
        if (condition_type !== 'customer__meta' && condition_type !== 'product_property__meta') {
            return;
        }

        // Get current method
        var current_method = element.find('.rp_wcdpd_' + alias + '_setting_fields_' + condition_type + ' .rp_wcdpd_' + key + '_' + alias + '_method').val();

        // Reference text field
        var text_field = element.find('.rp_wcdpd_' + alias + '_setting_fields_' + condition_type + ' .rp_wcdpd_' + key + '_' + alias + '_text');

        // Proceed depending on current method
        if (jQuery.inArray(current_method, ['is_empty', 'is_not_empty', 'is_checked', 'is_not_checked']) !== -1) {
            element.find('.rp_wcdpd_' + alias + '_setting_fields_' + condition_type).find('select').parent().removeClass('rp_wcdpd_' + alias + '_setting_fields_single').addClass('rp_wcdpd_' + alias + '_setting_fields_double');
            text_field.parent().css('display', 'none');
            jQuery.rightpress.clear_field_value(text_field);
            text_field.prop('disabled', true);
        }
        else {
            element.find('.rp_wcdpd_' + alias + '_setting_fields_' + condition_type).find('select').parent().removeClass('rp_wcdpd_' + alias + '_setting_fields_double').addClass('rp_wcdpd_' + alias + '_setting_fields_single');
            element.find('.rp_wcdpd_' + alias + '_setting_fields_' + condition_type).find('.rp_wcdpd_' + key + '_' + alias + '_text').parent().css('display', 'block');
            text_field.prop('disabled', false);
        }
    }

    /**
     * Fix fields of coupons applied condition
     */
    function fix_coupons_applied_condition(key, alias, element, condition_type)
    {
        // Only proceed if condition type is coupons applied
        if (condition_type !== 'cart__coupons' && condition_type !== 'product_other__wc_coupons_applied') {
            return;
        }

        // Get current method
        var current_method = element.find('.rp_wcdpd_' + alias + '_setting_fields_' + condition_type + ' .rp_wcdpd_' + key + '_' + alias + '_method').val();

        // Reference coupons field
        var coupons_field = element.find('.rp_wcdpd_' + alias + '_setting_fields_' + condition_type + ' .rp_wcdpd_' + key + '_' + alias + '_coupons');

        // Proceed depending on current method
        if (jQuery.inArray(current_method, ['at_least_one_any', 'none_at_all']) !== -1) {
            element.find('.rp_wcdpd_' + alias + '_setting_fields_' + condition_type).find('select').parent().removeClass('rp_wcdpd_' + alias + '_setting_fields_single').addClass('rp_wcdpd_' + alias + '_setting_fields_triple');
            coupons_field.parent().css('display', 'none');
            jQuery.rightpress.clear_field_value(coupons_field);
            coupons_field.prop('disabled', true);
        }
        else {
            element.find('.rp_wcdpd_' + alias + '_setting_fields_' + condition_type).find('select').parent().removeClass('rp_wcdpd_' + alias + '_setting_fields_triple').addClass('rp_wcdpd_' + alias + '_setting_fields_single');
            coupons_field.parent().css('display', 'block');
            coupons_field.prop('disabled', false);
        }
    }

    /**
     * Fix product group element
     */
    function fix_group_product(key, element)
    {
        // Product condition type
        element.find('.rp_wcdpd_' + key + '_group_product_type').on('change', function() {
            toggle_group_product_items_field(key, element);
        });
        toggle_group_product_items_field(key, element);
    }

    /**
     * Toggle visibility of product group items fields
     */
    function toggle_group_product_items_field(key, element)
    {
        // Get current group_product type
        var current_type = element.find('.rp_wcdpd_' + key + '_group_product_type').val();

        // Show fields related to current type
        element.find('.rp_wcdpd_group_product_setting_fields_' + current_type).each(function() {
            jQuery(this).css('display', 'block');
            toggle_form_field_visibility(jQuery(this), true);
        });

        // Hide other currently displayed fields
        element.find('.rp_wcdpd_group_product_setting_fields').not('.rp_wcdpd_group_product_setting_fields_' + current_type).has('select:enabled').each(function() {
            jQuery(this).css('display', 'none');
            toggle_form_field_visibility(jQuery(this), false);
        });
    }

    /**
     * Initialize Select2 multiselect
     */
    function initialize_select2_multiselect(key, element, type)
    {
        // Field is not multiselect
        if (!jQuery.rightpress.field_is_multiselect(element)) {
            return;
        }

        var config = {
            width: '100%',
            minimumInputLength: 1,
            placeholder: rp_wcdpd.labels.select2_placeholder,
            escapeMarkup: function (text) {
                return text;
            },
            language: {
                noResults: function (params) {
                    return rp_wcdpd.labels.select2_no_results;
                }
            },
            ajax: {
                url:        rp_wcdpd.ajaxurl,
                type:       'POST',
                dataType:   'json',
                delay:      250,
                dataFilter: jQuery.rightpress.sanitize_json_response,
                data: function(params) {
                    return {
                        query:      params.term,
                        action:     'rp_wcdpd_load_multiselect_options',
                        type:       parse_multiselect_subject(key, element, type),
                        selected:   element.val()
                    };
                },
                processResults: function(data, page) {
                    return {
                        results: data.results
                    };
                }
            }
        };

        // Initialize Select2
        if (typeof RP_Select2 !== 'undefined') {
            RP_Select2.call(element, config);
        }
        // Initialize Select2
        else if (typeof element.selectWoo !== 'undefined') {
            element.selectWoo(config);
        }
    }

    /**
     * Parse multiselect field subject
     */
    function parse_multiselect_subject(key, element, type)
    {
        var subject = '';

        // Fix type for bogo products
        var type = (typeof type !== 'undefined' ? type : 'field_bogo');

        jQuery.each(element.attr('class').split(/\s+/), function(index, item) {
            if (item.indexOf('rp_wcdpd_' + key + '_' + type + '_') > -1) {
                subject = item.replace('rp_wcdpd_' + key + '_' + type + '_', '');
                return;
            }
        });

        return subject;
    }

    /**
     * Fix row header
     */
    function fix_row_header(element, key, config)
    {

        // Reference row
        var row = element.hasClass('.rp_wcdpd_row') ? element : element.closest('.rp_wcdpd_row');

        /**
         * TITLE
         */

        // Get title placeholder
        var title = rp_wcdpd.labels.row_note_placeholder;

        // Get selector
        var selector = key === 'product_pricing' ? 'note' : 'title';

        // Get title from config
        if (config) {

            // Check if config has value
            if (typeof config[selector] !== 'undefined' && config[selector] !== '') {

                // Set title from config
                title = config[selector];
            }
        }
        // Get title from field
        else {

            var title_from_field = row.find('.rp_wcdpd_' + key + '_field_' + selector).val();

            // Check if field has value
            if (title_from_field !== 'undefined' && title_from_field !== '') {

                // Set title from field
                title = title_from_field;
            }
        }

        // Set title
        row.find('.rp_wcdpd_row_title_title').html(title).css('display', 'inline-block');

        /**
         * NOTE
         */

        // Check rule type is not product pricing
        if (key !== 'product_pricing') {

            // Set note to empty string
            var note = '';

            // Get note from config
            if (config) {

                // Check if config has value
                if (typeof config.note !== 'undefined' && config.note !== '') {

                    // Set note from config
                    note = config.note;
                }
            }
            // Get note from field
            else {

                var note_from_field = row.find('.rp_wcdpd_' + key + '_field_note').val();

                // Check if field has value
                if (note_from_field !== 'undefined' && note_from_field !== '') {

                    // Set note from field
                    note = note_from_field;
                }
            }

            // Set note
            row.find('.rp_wcdpd_row_title_note').html(note).css('display', (note === '' ? 'none' : 'inline-block'));
        }

        /**
         * METHOD
         */

        // Display method
        if (key === 'product_pricing') {

            // Get method key
            var method_key = config ? config.method : row.find('.rp_wcdpd_product_pricing_field_method').val();

            // Check if method is BOGO
            var is_bogo = ['bogo', 'bogo_xx'].indexOf(method_key) !== -1;
            var is_bogo_repeat = ['bogo_repeat', 'bogo_xx_repeat'].indexOf(method_key) !== -1;

            // Get BOGO quantities
            if (is_bogo || is_bogo_repeat) {
                var bogo_purchase = config ? config.bogo_purchase_quantity : row.find('.rp_wcdpd_product_pricing_field_bogo_purchase_quantity').val();
                var bogo_receive = config ? config.bogo_receive_quantity : row.find('.rp_wcdpd_product_pricing_field_bogo_receive_quantity').val();
            }

            // Get method text
            if ((is_bogo || is_bogo_repeat) && bogo_purchase !== '' && bogo_receive !== '') {
                var property_key = 'title_format_bogo' + (is_bogo_repeat ? '_repeat' : '');
                var method_text = rp_wcdpd[property_key].replace('{{x}}', bogo_purchase).replace('{{y}}', bogo_receive);
            }
            else {
                var method_text = rp_wcdpd.product_pricing_method_titles[method_key];
            }

            // Display method text
            row.find('.rp_wcdpd_row_title_method').html(method_text).css('display', 'inline-block');
        }

        /**
         * PRICING
         */

        // Get method key
        var method_key = config ? config.method : row.find('.rp_wcdpd_' + key + '_field_method').val();

        // Select selector
        if (['bogo', 'bogo_repeat', 'bogo_xx', 'bogo_xx_repeat'].indexOf(method_key) !== -1) {
            var selector = 'bogo_pricing';
        }
        else if (['group', 'group_repeat'].indexOf(method_key) !== -1) {
            var selector = 'group_pricing';
        }
        else {
            var selector = 'pricing';
        }

        // Get pricing settings
        var pricing_method = config ? config[selector + '_method'] : row.find('.rp_wcdpd_' + key + '_field_' + selector + '_method:enabled').val();
        var pricing_value = config ? config[selector + '_value'] : row.find('.rp_wcdpd_' + key + '_field_' + selector + '_value:enabled').val();

        // Both values are set
        if (typeof pricing_method !== 'undefined' && pricing_method !== '' && typeof pricing_value !== 'undefined' && pricing_value !== '' && jQuery.isNumeric(pricing_value)) {
            var pricing_string = format_pricing_string(pricing_method, pricing_value);
            row.find('.rp_wcdpd_row_title_pricing').html(pricing_string).css('display', 'inline-block');
        }
        // At least one value is not set
        else {
            row.find('.rp_wcdpd_row_title_pricing').html('').css('display', 'none');
        }
    }

    /**
     * Format pricing string
     */
    function format_pricing_string(pricing_method, pricing_value)
    {
        var prepend = '';
        var append  = '';

        switch (pricing_method) {

            case 'discount__amount':
            case 'discount__percentage':
                prepend = '-';
                break;

            case 'fee__amount':
            case 'fee__percentage':
                prepend = '+';
                break;

            case 'discount__amount_per_product':
                prepend = '-';
                append  = ' ' + rp_wcdpd.labels.per_item;
                break;

            case 'discount_per_cart_item__amount':
            case 'discount_per_cart_item__percentage':
                prepend = '-';
                append  = ' ' + rp_wcdpd.labels.per_cart_item;
                break;

            case 'discount_per_cart_line__amount':
                prepend = '-';
                append  = ' ' + rp_wcdpd.labels.per_cart_line;
                break;

            case 'discount__amount_per_group':
                prepend = '-';
                append  = ' ' + rp_wcdpd.labels.per_group;
                break;

            case 'fixed__price_per_product':
                append  = ' ' + rp_wcdpd.labels.per_item;
                break;

            case 'fixed__price_per_group':
                append  = ' ' + rp_wcdpd.labels.per_group;
                break;

            case 'fee_per_cart_item__amount':
            case 'fee_per_cart_item__percentage':
                prepend = '+';
                append  = ' ' + rp_wcdpd.labels.per_cart_item;
                break;

            case 'fee_per_cart_line__amount':
                prepend = '+';
                append  = ' ' + rp_wcdpd.labels.per_cart_line;
                break;
        }

        pricing_value = Math.abs(pricing_value);

        // Format amount as percentage
        if (pricing_method.endsWith('__percentage')) {
            pricing_value += '%';
        }
        // Format amount
        else {

            // Ensure required amount of decimal places are displayed
            pricing_value = pricing_value.toFixed(Math.max(rp_wcdpd.price_decimals, (pricing_value.toString().split('.')[1] || []).length));

            // Format amount
            pricing_value = rp_wcdpd.price_format.replace('{{value}}', pricing_value);
        }

        // Join strings
        return prepend + pricing_value + append;
    }

    /**
     * Display correct product pricing settings area
     */
    function toggle_product_pricing_settings(element, key)
    {
        var current_method = element.val();
        var row = element.closest('.rp_wcdpd_row');

        // Display fields for current method
        row.find('.rp_wcdpd_if_' + current_method).each(function() {

            // Display container
            jQuery(this).css('display', 'block');

            // Only display/enable actual fields if current method is not group (group product fields are controlled by another method)
            if ((current_method !== 'group' && current_method !== 'group_repeat') || !jQuery(this).hasClass('rp_wcdpd_row_content_product_pricing_group_row')) {
                toggle_form_field_visibility(jQuery(this), true);
            }
        });

        // Hide other not currently hidden fields
        row.find('.rp_wcdpd_if').not('.rp_wcdpd_if_' + current_method).filter(function() { return jQuery(this).css('display') !== 'none'; }).each(function() {

            var to_hide = jQuery(this);

            // Delete product conditions if product conditions wrapper is selected
            jQuery.each(['bogo_product_condition', 'product_condition'], function(index, alias) {
                if (to_hide.hasClass('rp_wcdpd_row_content_' + alias + 's_row')) {
                    remove_child_wrapper(key, alias, row);
                    add_no(key, (alias + 's'), row);
                }
            });

            // Hide
            to_hide.css('display', 'none');

            // Toggle field visibility
            toggle_form_field_visibility(to_hide, false);
        });

        // Promotion type width
        row.find('.rp_wcdpd_product_pricing_field_method').closest('.rp_wcdpd_field').each(function() {

            jQuery(this).removeClass('rp_wcdpd_field_single rp_wcdpd_field_double');

            if (current_method === 'simple' || current_method === 'exclude' || current_method === 'restrict_purchase') {
                jQuery(this).addClass('rp_wcdpd_field_double');
            }
            else {
                jQuery(this).addClass('rp_wcdpd_field_single');
            }
        });

        // Fix group product inputs
        if (current_method === 'group' || current_method === 'group_repeat') {
            row.find('.rp_wcdpd_group_product').each(function() {
                toggle_group_product_items_field(key, jQuery(this));
            });
        }

        // Toggle volume rule pricing methods
        if (current_method === 'bulk' || current_method === 'tiered') {
            toggle_volume_pricing_methods(element, key);
        }

        // Clear quantity ranges
        row.find('.rp_wcdpd_quantity_range_wrapper').each(function() {
            if (current_method !== 'bulk' && current_method !== 'tiered') {
                remove_child_wrapper(key, 'quantity_range', row);
                add_no(key, 'quantity_ranges', row);
            }
        });

        // Clear group products
        row.find('.rp_wcdpd_group_product_wrapper').each(function() {
            if (current_method !== 'group' && current_method !== 'group_repeat') {
                remove_child_wrapper(key, 'group_product', row);
                add_no(key, 'group_products', row);
            }
        });

        // Hide exclusivity field for some pricing methods
        row.find('.rp_wcdpd_product_pricing_field_exclusivity').each(function() {
            var displayed = (current_method !== 'exclude' && current_method !== 'restrict_purchase');
            jQuery(this).css('display', (displayed ? 'block' : 'none'));
            jQuery(this).prop('disabled', !displayed);

            if (!displayed) {
                jQuery.rightpress.clear_field_value(jQuery(this));
            }
        });

        // Add empty quantity range
        if (current_method === 'bulk' || current_method === 'tiered') {
            if (!row.find('.rp_wcdpd_quantity_range_wrapper').length) {
                row.find('.rp_wcdpd_add_quantity_range button').click();
            }
        }

        // Add empty group product
        if (current_method === 'group' || current_method === 'group_repeat') {
            if (!row.find('.rp_wcdpd_group_product_wrapper').length) {
                row.find('.rp_wcdpd_add_group_product button').click();
            }
        }

        // Fix row header
        fix_row_header(row, key, false);
    }

    /**
     * Toggle volume pricing methods
     */
    function toggle_volume_pricing_methods(element, key)
    {
        var row = element.closest('.rp_wcdpd_row');
        var method = row.find('.rp_wcdpd_product_pricing_field_method').val();

        // Iterate over all pricing method fields in this rule (one for each quantity range)
        row.find('.rp_wcdpd_product_pricing_quantity_range_pricing_method').each(function() {

            // Get option to remove
            var current_option = jQuery(this).find('option[value="fixed__price_per_range"]');

            // Select another value if selected option is about to be removed
            if (jQuery(this).val() === 'fixed__price_per_range' && method === 'bulk') {
                jQuery(this).val('fixed__price');
            }

            // Add missing option
            if (method === 'tiered' && !current_option.length && jQuery(this).data('option_fixed__price_per_range_label')) {
                jQuery(this).find('optgroup').last().append('<option value="fixed__price_per_range">' + jQuery(this).data('option_fixed__price_per_range_label') + '</option>');
            }

            // Remove option if it exists
            if (method === 'bulk' && current_option.length) {
                jQuery(this).data('option_fixed__price_per_range_label', current_option.text());
                current_option.remove();
            }
        });
    }

    /**
     * Toggle cart item settings
     */
    function toggle_cart_item_settings(element, key)
    {
        var current_pricing_method = element.val();
        var row = element.closest('.rp_wcdpd_row');

        // Show product selection
        if (jQuery.inArray(current_pricing_method, ['discount_per_cart_item__amount', 'discount_per_cart_item__percentage', 'discount_per_cart_line__amount', 'fee_per_cart_item__amount', 'fee_per_cart_item__percentage', 'fee_per_cart_line__amount']) !== -1) {
            row.find('.rp_wcdpd_row_content_product_conditions_row').css('display', 'block');
        }
        // Hide product selection
        else {
            remove_child_wrapper(key, 'product_condition', row);
            add_no(key, 'product_conditions', row);
            row.find('.rp_wcdpd_row_content_product_conditions_row').css('display', 'none');
        }
    }

    /**
     * Toggle visibility of form fields contained by element
     */
    function toggle_form_field_visibility(element, displayed)
    {
        // Iterate over all form fields
        element.find('input, select').each(function() {

            // Enable/disable fields
            jQuery(this).prop('disabled', !displayed);

            // Clear field values
            if (!displayed) {
                jQuery.rightpress.clear_field_value(jQuery(this));
            }
        });
    }

    /**
     * Refresh accordion
     */
    function refresh_accordion(key)
    {
        jQuery('#rp_wcdpd_' + key + ' #rp_wcdpd_rule_wrapper').accordion('refresh');
        jQuery('#rp_wcdpd_' + key + ' #rp_wcdpd_rule_wrapper').accordion('option', 'active', -1);
    }

    /**
     * Open requested rule on page load
     */
    if (typeof rp_wcdpd.open_rule_uid === 'string' && rp_wcdpd.open_rule_uid !== '') {

        // Reference wrapper
        var wrapper = jQuery('#rp_wcdpd_rule_wrapper');

        // Check if wrapper was selected
        if (wrapper.length) {

            // Find panel with this uid
            var row = wrapper.find('.rp_wcdpd_row input[value="' + rp_wcdpd.open_rule_uid + '"]').closest('.rp_wcdpd_row');

            // Check if row was selected
            if (row.length) {
                jQuery('#rp_wcdpd_rule_wrapper').accordion('option', 'active', row.index());
            }
        }
    }

    /**
     * Toggle discount/fee value input
     */
    jQuery('.rp_wcdpd_setting_total_limit').on('change', function() {
        var display = jQuery(this).val() !== '0';
        jQuery('.rp_wcdpd_setting_total_limit_value').prop('disabled', !display).css('display', (display ? 'inline-block' : 'none'));
    }).change();


































    /**
     * HELPER
     * Append template with values to selected element's content
     */
    function append(selector, template, values)
    {
        var html = get_template(template, values);

        if (typeof selector === 'object') {
            selector.append(html);
        }
        else {
            jQuery(selector).append(html);
        }
    }

    /**
     * HELPER
     * Prepend template with values to selected element's content
     */
    function prepend(selector, template, values)
    {
        var html = get_template(template, values);

        if (typeof selector === 'object') {
            selector.prepend(html);
        }
        else {
            jQuery(selector).prepend(html);
        }
    }

    /**
     * HELPER
     * Get template's html code
     */
    function get_template(template, values)
    {
        return populate_template(jQuery('#rp_wcdpd_' + template + '_template').html(), values);
    }

    /**
     * HELPER
     * Populate template with values
     */
    function populate_template(template, values)
    {
        for (var key in values) {
            if (values.hasOwnProperty(key)) {
                template = replace_macro(template, key, values[key]);
            }
        }

        return template;
    }

    /**
     * HELPER
     * Replace all instances of macro in string
     */
    function replace_macro(string, macro, value)
    {
        var macro = '{' + macro + '}';
        var regex = new RegExp(macro, 'g');
        return string.replace(regex, value);
    }






    /**
     * We are done by now, remove preloader
     */
    jQuery('#rp_wcdpd_preloader').remove();


});
