///////////////////////////////////////////////////////////////////////////////////
//  Tree Management Section
///////////////////////////////////////////////////////////////////////////////////
/*global document, window, Image */

function CollectionTreeManager(formName)
{
    this.categories = [];

    this.formName = formName;

    // The list of collections that will be selected when the page is displayed
    this.initialSelections = [];

    // The cache of images that are used in the collection tree
    this.imageCache = [];
}

/**
 * Sets the array of collections that should initially be checked.
 * @param initCollections
 */
CollectionTreeManager.prototype.setInitialCollections = function(initCollections)
{
    if (initCollections.length == 1 && initCollections[0] === "")
    {
        initCollections = [];
    }

    this.initialSelections = initCollections;
};

/**
 * Sets the list of categories to be displayed on this page.
 * @param cats
 */
CollectionTreeManager.prototype.setCategories = function(cats)
{
    if (cats.length == 1 && cats[0] === "")
    {
        cats = [];
    }
    this.categories = cats;
};

/**
 * Gets the all occurances of checkboxes which corresponds to the collectionCode
 * @param collectionCode the collection code to search for
 */
CollectionTreeManager.prototype.getCheckBoxesFromCollectionCode = function(collectionCode)
{
    var ret = [];

    // Find the checkbox with the default collecion id
    var inputs = document.getElementsByTagName("input");
    for (var i = 0; i < inputs.length; i++)
    {
        if (inputs[i].type == "checkbox")
        {
            var checkBoxValue = inputs[i].value;
            if (collectionCode == checkBoxValue ||
                collectionCode == this.extractId(checkBoxValue))
            {
                ret.push(inputs[i]);
            }
        }
    }

    return ret;
};

/**
 * Expand or Collapse Single Tree Node
 * @param item the id of the node to toggle
 */
CollectionTreeManager.prototype.toggle = function(item)
{
    var obj = document.getElementById(item);

    if (obj.style.display != "none")
    {
        this.collapseNode(item);
    }
    else
    {
        this.expandNode(item);
    }

    document.getElementById("all").checked = this.areAllChecked();

    // if all nodes are expanded, then change the main node to minus
    if (this.areAllNodesExpanded())
    {
        this.setImage("allCategoryImage", "minus");
    }

    // if all nodes are collapsed, then change the main node to plus
    if (this.areAllNodesCollapsed())
    {
        this.setImage("allCategoryImage", "plus");
    }

    return false;
};

/**
 * Collapse a tree node
 * @param item the id of the node to collapse
 */
CollectionTreeManager.prototype.collapseNode = function(item)
{
    var obj = document.getElementById(item);
    obj.style.display = "none";
    this.setImage("ximg" + item, "plus");
};

/**
 * Expand a tree node
 * @param item the id of the node to expand
 */
CollectionTreeManager.prototype.expandNode = function(item)
{
    var obj = document.getElementById(item);
    obj.style.display = "block";
    this.setImage("ximg" + item, "minus");
};

/**
 * Find out whether or not all of the nodes in the array are expanded
 * @param categoryArray the array of sub nodes of the category
 */
CollectionTreeManager.prototype.areAllNodesExpanded = function()
{
    return this.checkCategoryStyle("none");
};

/**
 * Find out whether or not all of the categories are collapsed
 */
CollectionTreeManager.prototype.areAllNodesCollapsed = function()
{
    return this.checkCategoryStyle("block");
};

/**
 * Checks to see if any of the categories have the passed in style.  If any do
 * have that style, return false
 * @param rejectedCategoryStyle the style to check for
 * @return true if none of the categories has the style
 */
CollectionTreeManager.prototype.checkCategoryStyle = function(rejectedCategoryStyle)
{
    var i;

    for (i = 0; i < this.categories; ++i)
    {
        if (document.getElementById(this.categories[i]).style.display == rejectedCategoryStyle)
        {
            return false;
        }
    }

    return true;
};

/**
 * toggles all of the categories in the tree
 */
CollectionTreeManager.prototype.toggleAll = function()
{
    var img = document.getElementById("allCategoryImage");

    if (String(img.src).indexOf("plus.gif") > 0)
    {
        this.expandAll();
        this.setImage("allCategoryImage", "minus");
    }
    else
    {
        this.collapseAll();
        this.setImage("allCategoryImage", "plus");
    }

    return false;
};

/**
 * Expands all nodes under a category
 */
CollectionTreeManager.prototype.expandAll = function()
{
    var i;
    for (i = 0; i < this.categories.length; i++)
    {
        this.expandNode(this.categories[i]);
    }
};

/**
 * Collapses all nodes under a category
 * @param categoryArray the array of nodes under the category
 */
CollectionTreeManager.prototype.collapseAll = function()
{
    var i;
    for (i = 0; i < this.categories.length; i++)
    {
        this.collapseNode(this.categories[i]);
    }
};

/**
 * Sets the checked state of the all source check box
 */
CollectionTreeManager.prototype.checkAllSources = function()
{
    if (typeof(document.getElementById("all")) != "undefined")
    {
        document.getElementById("all").checked = this.areAllChecked();
    }
};

/**
 * Check All Nodes Under a Group
 * @param item the root id of the item
 */
CollectionTreeManager.prototype.check_group = function(item)
{
    var category = document.getElementById("z" + item);
    var collections = document.getElementById(item).getElementsByTagName("input");
    for (var i = 0; i < collections.length; i++)
    {
        collections[i].checked = category.checked;
    }

    this.checkAllSources();
};

/**
 * Checks Status of a Group
 * @param item the root id of the item
 */
CollectionTreeManager.prototype.check_status = function(item)
{
    // get the category element identified by "item"
    var category = document.getElementById("z" + item);

    // get all of this category element's children
    var collections = document.getElementById(item).getElementsByTagName("input");

    // If there are no child nodes, then return
    if (collections.length === 0)
    {
        return;
    }

    // Count the children that are "checked"
    var check_count = 0;

    for (var i = 0; i < collections.length; i++)
    {
        if (collections[i].type == 'checkbox' && collections[i].checked)
        {
            check_count++;
        }
    }

    // if all the children are checked, then the parent is checked
    if (check_count > 0 && check_count == collections.length)
    {
        category.checked = true;
    }
    else
    {
        category.checked = false;
        // if some, but not all of the categories are checked, then expand this category node
        if (check_count !== 0)
        {
            this.expandNode(item);
        }
    }

    this.checkAllSources();
};

/**
 * Sets the checked state of the checkboxes
 * @param checked true to check, false to uncheck
 */
CollectionTreeManager.prototype.setAllCheckBoxes = function(checked)
{
    var root = document.getElementById("categoryBlock");
    var nodes = root.getElementsByTagName("input");
    if (nodes)
    {
        // set the check value for all check boxes
        for (var i = 0; i < nodes.length; i++)
        {
            if (nodes[i].type == "checkbox")
            {
                nodes[i].checked = checked;
            }
        }
    }
};

/**
 * Unchecks all checkboxes in the search form
 */
CollectionTreeManager.prototype.uncheckAll = function()
{
    this.setAllCheckBoxes(false);
};

/**
 * Checks all checkboxes in the search form
 */
CollectionTreeManager.prototype.checkAll = function()
{
    this.setAllCheckBoxes(true);
};

/**
 * Finds out if all of the checkboxes in the search form are checked
 */
CollectionTreeManager.prototype.areAllChecked = function()
{
    var root = document.getElementById("categoryBlock");
    var nodes = root.getElementsByTagName("input");
    if (!nodes)
    {
        return false;
    }

    for (var i = 0; i < nodes.length; i++)
    {
        if (nodes[i].type == "checkbox" && nodes[i].id != "all")
        {
            if (!nodes[i].checked)
            {
                return false;
            }
        }
    }

    return true;
};

/**
 * Extracts the collection id from a string that is the combination of category
 * id and collection id.
 * @param value
 */
CollectionTreeManager.prototype.extractId = function(value)
{
    var underIndex = value.indexOf("_");
    var ret = "";
    if (underIndex > 0)
    {
        ret = value.substr(underIndex + 1, value.length - 1);
    }

    return ret;
};

/**
 * adds an image to the image cache
 * @param imageName the name of the image
 * @param src the source of the image
 * @param alt the alt text
 */
CollectionTreeManager.prototype.addToImageCache = function(imageName, src, alt)
{
    this.imageCache[imageName] = new Image(11, 11);
    this.imageCache[imageName].src = src;
    this.imageCache[imageName].alt = alt;
};

/**
 * Set the image identified by imgId to the image with name: imgName
 * this assumes that there is an array of images named "imageCache"
 * that contains the image to set.
 * @param imgId
 * @param imgName
 */
CollectionTreeManager.prototype.setImage = function(imgId, imgName)
{
    document.images[imgId].src = this.imageCache[imgName].src;
    document.images[imgId].alt = this.imageCache[imgName].alt;
    document.images[imgId].title = this.imageCache[imgName].title;
};

/**
 * Handler for the onclick event from the "check all" checkbox
 * @param chkAllElement the check all checkbox
 */
CollectionTreeManager.prototype.toggleSelect = function()
{
    var chkAllElement = document.getElementById("all");

    if (chkAllElement.checked)
    {
        this.checkAll();
    }
    else
    {
        this.uncheckAll();
    }
};

/**
 * Gets the ids of the check boxes that should be set
 */
CollectionTreeManager.prototype.getInitialCheckBoxIds = function()
{
    var initialCheckBoxIds = [];
    var i;
    var j;
    var cb;

    for (i = 0; i < this.initialSelections.length; ++i)
    {
        cb = this.getCheckBoxesFromCollectionCode(this.initialSelections[i]);
        for (j = 0; j < cb.length; ++j)
        {
            initialCheckBoxIds.push(cb[j].value);
        }
    }

    return initialCheckBoxIds;
};

/**
 * Sets up the tree after the page has been loaded.
 */
CollectionTreeManager.prototype.setupCategoryTree = function()
{
    var i;
    var initialCheckBoxIds;

    if (this.initialSelections.length === 0 || this.initialSelections[0] == "NONE")
    {
        this.uncheckAll();
    }
    else if (this.initialSelections[0] == "ALL")
    {
        this.checkAll();
    }
    else
    {
        // Set up the initial set of collections
        initialCheckBoxIds = this.getInitialCheckBoxIds();

        var collectionCheckBoxes = document.forms[this.formName].selectedCollections;
        if (typeof(collectionCheckBoxes) == "undefined")
        {
            collectionCheckBoxes = document.forms[this.formName].collections;
        }

        if (typeof(collectionCheckBoxes) == "undefined")
        {
            window.alert("Error:  Why are there no collections?");
            return;
        }

        for (i = 0; i < collectionCheckBoxes.length; i++)
        {
            var collectionCheckbox = collectionCheckBoxes[i];
            collectionCheckbox.checked = false;
            for (var j = 0; j < initialCheckBoxIds.length; j++)
            {
                if (collectionCheckbox.value == initialCheckBoxIds[j] || this.extractId(collectionCheckbox.value) == initialCheckBoxIds[j])
                {
                    collectionCheckbox.checked = true;
                }
            }
        }

        // go through each category and decide if we need to show it
        for (i = 0; i < this.categories.length; i++)
        {
            var categoryName = "cat" + (i + 1);
            if (document.getElementById("z" + categoryName))
            {
                this.check_status(categoryName);
            }
        }
    }

    this.checkAllSources();

    if (this.categories.length === 1)
    {
        this.expandAll(this.categories);
    }
};

