/* The contents of this file are subject to the Mozilla Public
 * License Version 1.1 (the "License"); you may not use this file
 * except in compliance with the License. You may obtain a copy of
 * the License at http://www.mozilla.org/MPL/
 * 
 * Software distributed under the License is distributed on an "AS
 * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
 * implied. See the License for the specific language governing
 * rights and limitations under the License.
 * 
 * The Original Code is the Bugzilla Bug Tracking System.
 * 
 * The Initial Developer of the Original Code is Netscape Communications
 * Corporation. Portions created by Netscape are
 * Copyright (C) 1998 Netscape Communications Corporation. All
 * Rights Reserved.
 * 
 * Contributor(s): Christian Reis <kiko@async.com.br>
 */

// Functions to update form select elements based on a
// collection of javascript arrays containing strings.

/**
 * Reads the selected classifications and updates product, component,
 * version and milestone lists accordingly.
 *
 * @param  classfield Select element that contains classifications.
 * @param  product    Select element that contains products.
 * @param  component  Select element that contains components. Can be null if
 *                    there is no such element to update.
 * @param  version    Select element that contains versions. Can be null if
 *                    there is no such element to update.
 * @param  milestone  Select element that contains milestones. Can be null if
 *                    there is no such element to update.
 *
 * @global prods      Array of products indexed by classification name.
 * @global first_load Boolean; true if this is the first time this page loads
 *                    or false if not.
 * @global last_sel   Array that contains last list of products so we know what
 *                    has changed, and optimize for additions.
 */
function selectClassification(classfield, product, component, version, milestone) {
    // This is to avoid handling events that occur before the form
    // itself is ready, which could happen in buggy browsers.
    if (!classfield)
        return;

    // If this is the first load and nothing is selected, no need to
    // merge and sort all lists; they are created sorted.
    if ((first_load) && (classfield.selectedIndex == -1)) {
        first_load = false;
        return;
    }
    
    // Don't reset first_load as done in selectProduct. That's because we
    // want selectProduct to handle the first_load attribute.

    // Stores classifications that are selected.
    var sel = Array();

    // True if sel array has a full list or false if sel contains only
    // new classifications that are to be merged to the current list.
    var merging = false;

    // If nothing selected, pick all.
    var findall = classfield.selectedIndex == -1;
    sel = get_selection(classfield, findall, false);
    if (!findall) {
        // Save sel for the next invocation of selectClassification().
        var tmp = sel;
    
        // This is an optimization: if we have just added classifications to an
        // existing selection, no need to clear the form elements and add
        // everything again; just merge the new ones with the existing
        // options.
        if ((last_sel.length > 0) && (last_sel.length < sel.length)) {
            sel = fake_diff_array(sel, last_sel);
            merging = true;
        }
        last_sel = tmp;
    }

    // Save original options selected.
    var saved_prods = get_selection(product, false, true, null);

    // Do the actual fill/update, reselect originally selected options.
    updateSelect(prods, sel, product, merging, null);
    restoreSelection(product, saved_prods);
    selectProduct(product, component, version, milestone, null);
}

/**
 * Reads the selected products and updates component, version and milestone
 * lists accordingly.
 *
 * @param  product    Select element that contains products.
 * @param  component  Select element that contains components. Can be null if
 *                    there is no such element to update.
 * @param  version    Select element that contains versions. Can be null if
 *                    there is no such element to update.
 * @param  milestone  Select element that contains milestones. Can be null if
 *                    there is no such element to update.
 * @param  anyval     Value to use for a special "Any" list item. Can be null
 *                    to not use any. If used must and will be first item in
 *                    the select element.
 *
 * @global cpts       Array of arrays, indexed by product name. The subarrays
 *                    contain a list of components to be fed to the respective
 *                    select element.
 * @global vers       Array of arrays, indexed by product name. The subarrays
 *                    contain a list of versions to be fed to the respective
 *                    select element.
 * @global tms        Array of arrays, indexed by product name. The subarrays
 *                    contain a list of milestones to be fed to the respective
 *                    select element.
 * @global first_load Boolean; true if this is the first time this page loads
 *                    or false if not.
 * @global last_sel   Array that contains last list of products so we know what
 *                    has changed, and optimize for additions.
 */
function selectProduct(product, component, version, milestone, anyval) {
    // This is to avoid handling events that occur before the form
    // itself is ready, which could happen in buggy browsers.
    if (!product)
        return;

    // Do nothing if no products are defined. This is to avoid the
    // "a has no properties" error from merge_arrays function.
    if (product.length == (anyval != null ? 1 : 0))
        return;

    // If this is the first load and nothing is selected, no need to
    // merge and sort all lists; they are created sorted.
    if ((first_load) && (product.selectedIndex == -1)) {
        first_load = false;
        return;
    }

    // Turn first_load off. This is tricky, since it seems to be
    // redundant with the above clause. It's not: if when we first load
    // the page there is _one_ element selected, it won't fall into that
    // clause, and first_load will remain 1. Then, if we unselect that
    // item, selectProduct will be called but the clause will be valid
    // (since selectedIndex == -1), and we will return - incorrectly -
    // without merge/sorting.
    first_load = false;

    // Stores products that are selected.
    var sel = Array();

    // True if sel array has a full list or false if sel contains only
    // new products that are to be merged to the current list.
    var merging = false;

    // If nothing is selected, or the special "Any" option is selected
    // which represents all products, then pick all products so we show
    // all components.
    var findall = (product.selectedIndex == -1
                   || (anyval != null && product.options[0].selected));

    if (useclassification) {
        // Update index based on the complete product array.
        sel = get_selection(product, findall, true, anyval);
        for (var i=0; i<sel.length; i++)
           sel[i] = prods[sel[i]];
    }
    else {
        sel = get_selection(product, findall, false, anyval);
    }
    if (!findall) {
        // Save sel for the next invocation of selectProduct().
        var tmp = sel;

        // This is an optimization: if we have just added products to an
        // existing selection, no need to clear the form controls and add
        // everybody again; just merge the new ones with the existing
        // options.
        if ((last_sel.length > 0) && (last_sel.length < sel.length)) {
            sel = fake_diff_array(sel, last_sel);
            merging = true;
        }
        last_sel = tmp;
    }

    // Do the actual fill/update.
    if (component) {
        var saved_cpts = get_selection(component, false, true, null);
        updateSelect(cpts, sel, component, merging, anyval);
        restoreSelection(component, saved_cpts);
    }

    if (version) {
        var saved_vers = get_selection(version, false, true, null);
        updateSelect(vers, sel, version, merging, anyval);
        restoreSelection(version, saved_vers);
    }

    if (milestone) {
        var saved_tms = get_selection(milestone, false, true, null);
        updateSelect(tms, sel, milestone, merging, anyval);
        restoreSelection(milestone, saved_tms);
    }
}

/**
 * Adds to the target select element all elements from array that
 * correspond to the selected items.
 *
 * @param array   An array of arrays, indexed by number. The array should
 *                contain elements for each selection.
 * @param sel     A list of selected items, either whole or a diff depending
 *                on merging parameter.
 * @param target  Select element that is to be updated.
 * @param merging Boolean that determines if we are merging in a diff or
 *                substituting the whole selection. A diff is used to optimize
 *                adding selections.
 * @param anyval  Name of special "Any" value to add. Can be null if not used.
 * @return        Boolean; true if target contains options or false if target
 *                is empty.
 *
 * Example (compsel is a select form element):
 *
 *     var components = Array();
 *     components[1] = [ 'ComponentA', 'ComponentB' ];
 *     components[2] = [ 'ComponentC', 'ComponentD' ];
 *     source = [ 2 ];
 *     updateSelect(components, source, compsel, false, null);
 *
 * This would clear compsel and add 'ComponentC' and 'ComponentD' to it.
 */
function updateSelect(array, sel, target, merging, anyval) {
    var i, item;

    // If we have no versions/components/milestones.
    if (array.length < 1) {
        target.options.length = 0;
        return false;
    }

    if (merging) {
        // Array merging/sorting in the case of multiple selections
        // merge in the current options with the first selection.
        item = merge_arrays(array[sel[0]], target.options, 1);

        // Merge the rest of the selection with the results.
        for (i = 1 ; i < sel.length ; i++)
            item = merge_arrays(array[sel[i]], item, 0);
    }
    else if (sel.length > 1) {
        // Here we micro-optimize for two arrays to avoid merging with a
        // null array.
        item = merge_arrays(array[sel[0]],array[sel[1]], 0);

        // Merge the arrays. Not very good for multiple selections.
        for (i = 2; i < sel.length; i++)
            item = merge_arrays(item, array[sel[i]], 0);
    }
    else {
        // Single item in selection, just get me the list.
        item = array[sel[0]];
    }

    // Clear current selection.
    target.options.length = 0;

    // Add special "Any" value back to the list.
    if (anyval != null)
        target.options[0] = new Option(anyval, "");

    // Load elements of list into select element.
    for (i = 0; i < item.length; i++)
        target.options[target.options.length] = new Option(item[i], item[i]);

    return true;
}

/**
 * Selects items in select element that are defined to be selected.
 *
 * @param control  Select element of which selected options are to be restored.
 * @param selnames Array of option names to select.
 */
function restoreSelection(control, selnames) {
    // Right. This sucks but I see no way to avoid going through the
    // list and comparing to the contents of the control.
    for (var j = 0; j < selnames.length; j++)
        for (var i = 0; i < control.options.length; i++)
            if (control.options[i].value == selnames[j])
                control.options[i].selected = true;
}

/**
 * Returns elements in a that are not in b.
 * NOT A REAL DIFF: does not check the reverse.
 *
 * @param  a First array to compare.
 * @param  b Second array to compare.
 * @return   Array of elements in a but not in b.
 */
function fake_diff_array(a, b) {
    var newsel = new Array();
    var found = false;

    // Do a boring array diff to see who's new.
    for (var ia in a) {
        for (var ib in b)
            if (a[ia] == b[ib])
                found = true;

        if (!found)
            newsel[newsel.length] = a[ia];

        found = false;
    }

    return newsel;
}

/**
 * Takes two arrays and sorts them by string, returning a new, sorted
 * array. The merge removes dupes, too.
 *
 * @param  a           First array to merge.
 * @param  b           Second array or an optionitem element to merge.
 * @param  b_is_select Boolean; true if b is an optionitem element (need to
 *                     access its value by item.value) or false if b is a
 *                     an array.
 * @return             Merged and sorted array.
 */
function merge_arrays(a, b, b_is_select) {
    var pos_a = 0;
    var pos_b = 0;
    var ret = new Array();
    var bitem, aitem;

    // Iterate through both arrays and add the larger item to the return
    // list. Remove dupes, too. Use toLowerCase to provide
    // case-insensitivity.
    while ((pos_a < a.length) && (pos_b < b.length)) {
        aitem = a[pos_a];
        if (b_is_select)
            bitem = b[pos_b].value;
        else
            bitem = b[pos_b];

        // Smaller item in list a.
        if (aitem.toLowerCase() < bitem.toLowerCase()) {
            ret[ret.length] = aitem;
            pos_a++;
        }
        else {
            // Smaller item in list b.
            if (aitem.toLowerCase() > bitem.toLowerCase()) {
                ret[ret.length] = bitem;
                pos_b++;
            }
            else {
                // List contents are equal, include both counters.
                ret[ret.length] = aitem;
                pos_a++;
                pos_b++;
            }
        }
    }

    // Catch leftovers here. These sections are ugly code-copying.
    if (pos_a < a.length)
        for (; pos_a < a.length ; pos_a++)
            ret[ret.length] = a[pos_a];

    if (pos_b < b.length) {
        for (; pos_b < b.length; pos_b++) {
            if (b_is_select)
                bitem = b[pos_b].value;
            else
                bitem = b[pos_b];
            ret[ret.length] = bitem;
        }
    }

    return ret;
}

/**
 * Returns an array of indexes or values of options in a select form element.
 *
 * @param  control     Select form element from which to find selections.
 * @param  findall     Boolean; true to return all options or false to return
 *                     only selected options.
 * @param  want_values Boolean; true to return values and false to return
 *                     indexes.
 * @param  anyval      Name of a special "Any" value that should be skipped. Can
 *                     be null if not used.
 * @return             Array of all or selected indexes or values.
 */
function get_selection(control, findall, want_values, anyval) {
    var ret = new Array();

    if ((!findall) && (control.selectedIndex == -1))
        return ret;

    for (var i = (anyval != null ? 1 : 0); i < control.length; i++)
        if (findall || control.options[i].selected)
            ret[ret.length] = want_values ? control.options[i].value : i;

    return ret;
}
