/**
* Part of the Collection Workflow Integration System (CWIS)
* Copyright 2014 Edward Almasy and Internet Scout Research Group
* http://scout.wisc.edu/cwis/
*/

// Javascript routines for the FieldEditingUI.

(function(){
    /**
    * Toggle UI elements such that only those appropriate for a
    * selected field are visible.
    * @param subjectField HTML form field selecting which metadata
    *   field should be in use.
    */
    function modifySiblingFields( subjectField )
    {
        var field_id = jQuery(":selected", subjectField).attr("value"),
            field_type = jQuery(":selected", subjectField).attr("class").match(/field-type-[a-z]+/),
            topRow = subjectField.parent().parent().children(),
            valueSelectField = jQuery('.field-value-select', topRow),
            operatorField = jQuery('.field-operator', topRow);

        // if we don't already have one, snag a copy of the default operators list
        if (!operatorField.data("default_options")){
            operatorField.data("default_options", operatorField.html());
        }
        operatorField.html("").append(operatorField.data("default_options"));

        // remove operators not appropriate for this field type
        jQuery("option:not(."+field_type+")", operatorField).remove();

        // remove 'clear all' from required fields
        if (jQuery(":selected", subjectField).hasClass("required")) {
            jQuery("option[value=3]", operatorField).remove();
        }

        if (field_type == "field-type-flag" || field_type == "field-type-option" ||
            field_type == "field-type-multoption" ) {
            // if  we don't  already  have  one, snag  a  copy of  the
            // default select options list
            if (!valueSelectField.data("default_options")){
                valueSelectField.data("default_options", valueSelectField.html());
            }
            valueSelectField.html("").append(valueSelectField.data("default_options"));

            jQuery("option:not(.field-id-"+field_id+")", valueSelectField).remove();
        }

        showAppropriateEditFields( topRow );
    }

    /**
    * Toggle UI elements to show only appropriate edit fields for a selected field.
    * @param field_row <tr> containing the elements to consider.
    */
    function showAppropriateEditFields(field_row)
    {
        var subj_field = jQuery('.field-subject', field_row),
            valueSelectField = jQuery('.field-value-select', field_row),
            valueEditField = jQuery('.field-value-edit', field_row),
            valueEdit2Field = jQuery('.field-value-repl', field_row),
            valueQSField = jQuery('.field-value-qs', field_row),
            operatorField = jQuery('.field-operator', field_row),
            field_type = jQuery(":selected",subj_field).attr("class").match(/field-type-[a-z]+/),
            opType = jQuery(":selected", operatorField).attr("value");

        // for Clear All, nobody gets edit boxes
        if (opType == 3) {
            valueSelectField.hide();
            valueEditField.hide();
            valueEdit2Field.hide();
            valueQSField.hide();
            // for Find/Replace, we'll need the two text boxes
        } else if (opType == 7) {
            valueSelectField.hide();
            valueEditField.show();
            valueEdit2Field.show();
            valueQSField.hide();
            // otherwise, determine it by field type
        } else {
            if (field_type == "field-type-flag" || field_type == "field-type-option" ||
                field_type == "field-type-multoption") {
                valueSelectField.show();
                valueEditField.hide();
                valueEdit2Field.hide();
                valueQSField.hide();
            } else if (field_type == "field-type-controlledname" ||
                     field_type == "field-type-tree" ||
                     field_type == "field-type-reference") {
                valueQSField.show();

                var field_id = jQuery(":selected", subj_field).attr("value");
                valueQSField.attr("data-fieldid", field_id);

                // if the current field has a quicksearch setup, remove it
                //  otherwise, create one
                if (valueQSField.hasClass('cw-quicksearch-template')) {
                    valueQSField.removeClass('cw-quicksearch-template');
                } else {
                    $('.cw-quicksearch-display', valueQSField).autocomplete("destroy");
                }

                // and set up a new quicksearch widget using the right field
                QuickSearch(valueQSField);

                valueEditField.hide();
                valueEdit2Field.hide();
                valueSelectField.hide();
            } else {
                valueEditField.show();
                valueEdit2Field.hide();
                valueSelectField.hide();
                valueQSField.hide();
            }
        }
    }

    /**
    * Check if any edit rows are visible, show the 'no fields' message if not.
    */
    function toggleEmptyMessageIfNeeded()
    {
        // iterate over the empty messages, collecting the section
        // names we need to look for
        var sections = [];
        jQuery('.cw-feui-empty').each(function(i){
            sections.push( $(this).data('formname'));
        });

        jQuery.each(sections, function(k, v){
            if (jQuery('.'+v+'.field_row:not(.template_row)').length == 0) {
                jQuery('.'+v+'.cw-feui-empty').show();
            } else {
                jQuery('.'+v+'.cw-feui-empty').hide();
            }
        });
    }

    // do UI setup
    $(document).ready(function(){
        var subjectFields = jQuery(".field-subject:not(.field-static)");

        // hide elements that should be hidden
        subjectFields.each(function(){
            modifySiblingFields( jQuery(this) );
        });
        jQuery(".template_row").hide();

        toggleEmptyMessageIfNeeded();

        // watch for subject changes, alter field hiding as needed
        subjectFields.change( function(){
            // grab our table row
            var row = jQuery(this).parent().parent();

            // clear any error fields and remove error messages
            jQuery('.field-value-edit', row).removeClass('cw-form-error');
            jQuery('span.cw-feui-error', row).remove();

            // clear edit/replace values
            jQuery('.field-value-edit', row).attr('value','');
            jQuery('.field-value-repl', row).attr('value','');

            // rearrange visiable fields as needed
            modifySiblingFields( jQuery(this) );
        });

        // similarly, watch for operator fields changes and alter field hiding as needed
        var opFields = jQuery(".field-operator");
        opFields.change( function(){
            var topRow = jQuery(this).parent().parent().children();
            showAppropriateEditFields( topRow );
        });

        // handle clicking the add button
        jQuery(".cw-feui-add").click(function(){
            // grab the template row
            var tpl_row = $(this).parent().parent().prev();

            // make a copy of it, set the copy visible
            var new_row = tpl_row.clone(true);
            new_row.removeClass('template_row');
            tpl_row.before(new_row);
            new_row.show();

            // remove any 'modified' messages
            jQuery('.cw-form-modified').remove();
            toggleEmptyMessageIfNeeded();
        });

        // handle clicking the delete button
        jQuery(".cw-feui-delete").click(function(){
            $(this).parent().parent().remove();
            toggleEmptyMessageIfNeeded();
        });

        jQuery(".cw-feui-form").submit(function() {
            // remove the 'modified' notice and past error messages
            jQuery('.cw-form-modified').remove();
            jQuery('.field-value-edit').removeClass('cw-form-error');
            jQuery('span.cw-feui-error').remove();

            // validate timestamp, date, and number fields
            var rc = true;

            jQuery('.field_row:not(.template_row)').each(function(){
                var field_type,
                    field_value = jQuery('.field-value-edit', this).attr('value'),
                    subj_field = jQuery('.field-subject', this),
                    field_op = jQuery('.field-operator', this).attr('value');

                // extract the field id for the given row
                // if the value of the subject field starts with S_, then we're dealing with
                // a static field row and can pull the class from the input element directly.
                // otherwise, we're dealing with a selectable row, and
                // need to pull the class from the selected element of
                // the subject field.
                if (subj_field.attr('value').match(/S_/)) {
                    field_type = jQuery(subj_field).attr("class").match(
                            /field-type-[a-z]+/);
                } else {
                    field_type = jQuery(":selected", subj_field).attr("class").match(
                            /field-type-[a-z]+/);
                }

                // number fields should contain ints
                //  if operator is not 'clear all'
                if (field_type == "field-type-number" &&
                    field_op != 3) {
                    if (!field_value.match(/^[0-9]+$/)) {
                        jQuery('.field-value-edit', this).addClass('cw-form-error');
                        jQuery('.field-value-edit', this).parent().append(
                            '<span style="position: absolute;" class="cw-feui-error cw-form-error">Invalid value: not a whole number</span>');
                        rc = false;
                    }
                }
                // date and timestamp fields should be parsable dates
                //  if operator is not 'clear all'
                else if ((field_type == "field-type-date" ||
                          field_type == "field-type-timestamp") &&
                         field_op != 3 ) {
                    // trim times, they confuse javascript
                    field_value = field_value.replace(
                            / [0-9]{1,2}:[0-9]{2}:[0-9]{2}( AM| PM)?/,'')

                    // see if the date is parsable
                    if (isNaN(Date.parse(field_value))) {
                        jQuery('.field-value-edit', this).addClass('cw-form-error');
                        jQuery('.field-value-edit', this).parent().append(
                            '<span style="position: absolute;" class="cw-feui-error cw-form-error">Invalid date (try YYYY-MM-DD HH:MM:SS)</span>');
                        rc = false;
                    }
                }
            });

            // if anything went wrong, block the submission
            if (!rc) {
                return false;
            }

            // if everything was okay, remove the template rows before submission
            jQuery(".template_row").remove();

            // make sure that every select contains something to avoid parse problems
            jQuery(".field-value-select:empty").append(
                '<option value="0">--</option>');

        });
    });
}());
