// For a given field, iterate over the various if- or ifnot- classes.
// The callback should take the following arguments:
//
//     callback(field, other_field, test_string, is_positive)
//
// For example, the class if-yes-has-crabs would invoke:
//
//     callback(field, $('has-crabs'), 'yes', false)
//
function if_field_iterate(field, callback) {

    // Multiple CSS classes are space-separated.
    var classes = field.className.split(' ');

    // Iterate over each of the classes.
    for (var class_i = 0; class_i < classes.length; class_i++) {
        var clazz = classes[class_i];

        var prev_is_positive;
        var is_positive;
        var test_i;

        // Determine whether the class name begins with 'if-' or
        // 'ifnot-'.  Otherwise, ignore it.
        if (clazz.substring(0,3) === 'if-') {
            is_positive = true;
            test_i      = 3;
        } else if (clazz.substring(0,6) == 'ifnot-') {
            is_positive = false;
            test_i      = 6;
        } else {
            continue;
        }

        // Mixing if- and ifnot- classes doesn't make sense.
        if ($defined(prev_is_positive) && is_positive != prev_is_positive) {
            if_error('Cannot mix if- and ifnot- classes: ' + clazz);
            continue;
        }
        prev_is_positive = is_positive;

        // Search for the end of the test string, indicated by a '-'
        var test_j = clazz.indexOf('-', test_i);
        if (test_j == -1) {
            if_error('bad if clazz: ' + clazz);
            continue;
        }

        // Extract the test string and field name from the class name.
        var other_field_name = clazz.substring(test_j + 1);
        var test_string      = clazz.substring(test_i, test_j);

        // Lookup the other field in the DOM.
        var other_field = $(other_field_name);
        if (!$defined(other_field)) {
            if_error('no DOM element with id=' + other_field_name);
            continue;
        }

        // Invoke the user callback.
        callback(field, other_field, test_string, is_positive);
    }
}

// Compare the test strings for each of the if- (or ifnot-) classes.
//
// For if- classes,    returns true  if any of the test strings match,
//                             false if all of the test strings don't match
//
// For ifnot- classes, returns false if any of the test strings match,
//                             true  if all of the test strings don't match
//
function if_field_test(field) {

    // Iterate over each of the if- or ifnot- classes, and compare
    // the test string with the other field's value.
    var is_test_match  = false;
    var is_positive_all = false;

    if_field_iterate(field,
        function(field, other_field, test_string, is_positive) {
            if (!is_test_match) {
                var other_field_value = other_field.getValue().trim();
                is_test_match   = other_field_value == test_string;
                is_positive_all = is_positive;
            }
        }
    );

    return is_test_match == is_positive_all;
}


// Callback for change event.  Also used during initialization.
//
function if_field_onchange(field) {

    // Enable or disable the field, based on the test strings
    // of the if- or ifnot- classes.
    if (if_field_test(field)) {
        field.removeClass('disabled');
    } else {
        field.addClass   ('disabled');
    }
}

// Initialize the field by adding event handlers for each of the
// if- or ifnot- classes.
//
function if_field_init(field) {
    if_field_iterate(field,
        function(field, other_field, test_string, is_positive) {
            other_field.onchange = if_field_onchange.pass(field);
        }
    );
}

// Used during debugging, simply a wrapper around alert.
// TODO: Disable during production?
//
function if_error(string) {
    alert(string);
}

//
//
function submit_onchange() {
    if ($ES('.invalid').length > 0) {
        submit_disable();
    } else {
        submit_enable();
    }
}


function submit_change(disabled, opacity) {
    var button = $E('button');
    button.disabled = disabled;
    button.setStyle('opacity', opacity);
}

function submit_enable()  { submit_change(false, 1.0); }
function submit_disable() { submit_change(true,  0.5); }

// Returns true if the required field is valid, false if invalid.
//
function required_field_test(field) {
    var input = $E('input', field);
    var value = input.getValue().trim();
    return value != '';
}

// Callback for the change event.  Also used during initialization.
//
function required_field_onchange(field) {
    if (required_field_test(field)) {
        field.removeClass('invalid');
    } else {
        field.   addClass('invalid');
    }
}

// Initialize the required field by adding event handlers.
//
function required_field_init(field) {
    var input = $E('input', field);
    input.onchange = function() {
        required_field_onchange(field);
        submit_onchange(field);
    };
}

// Initialize all fields with the "if" and "required" classes.
//
window.addEvent('domready', function() {
    $ES('.if').each( function(field) {
        if_field_init(field);
        if_field_onchange(field);
    });

    $ES('.required').each( function(field) {
        required_field_init(field);
        required_field_onchange(field);
    });

    submit_onchange();
});

