/*global document, window, Image */


/**
 * @class CollectionTreeManager
 * @description Contains the list of checkboxes that are used to select
 * collections for a search
 * @constructor
 * @param {String} formName the name of the form that contains the collections
 */
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 = [];
}

CollectionTreeManager.noCollError = "<<uninitialized>>";

/**
 * Sets the array of collections that should initially be checked.
 * @param {Array} initCollections the collections that should be selected by default
 */
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 {Array} cats the aray of categories to set
 */
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 {String} collectionCode the collection code to search for
 * @reutrn {Array} the array of all checkboxes for the collection code
 */
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 {String} item the id of the node to expand
 * @return {Boolean} false to prevent event bubbling when used in click handler
 */
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 {String} 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 {String} 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
 * @return {Boolean} if all nodes are expanded
 */
CollectionTreeManager.prototype.areAllNodesExpanded = function()
{
    return this.checkCategoryStyle("none");
};

/**
 * Find out whether or not all of the categories are collapsed
 * @return {Boolean} if all nodes 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 {String} rejectedCategoryStyle the style to check for
 * @return {Boolean} 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
 * @return {Boolean} false to prevent event bubbling when used in click handler
 */
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 in the tree
 */
CollectionTreeManager.prototype.expandAll = function()
{
    var i;
    for (i = 0; i < this.categories.length; i++)
    {
        this.expandNode(this.categories[i]);
    }
};

/**
 * Collapses all nodes in the tree
 */
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 (document.getElementById("all") != null)
    {
        document.getElementById("all").checked = this.areAllChecked();
    }

    if (document.getElementById("all_simple") != null)
    {
        document.getElementById("all_simple").checked = this.areAllSimpleChecked();
    }
};

/**
 * Check All Nodes Under a Group
 * @param {String} 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 {String} 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();
};

/**
 * Gets all of the checkbox nodes under the category block
 * @return {Array} an array of checkbox elements
 */
CollectionTreeManager.prototype._getCheckboxElements = function(simple)
{
    var root;

    if(typeof(simple) != "undefined")
    {
        root  = document.getElementById("categoryBlock_simple");
    }
    else
    {
        root  = document.getElementById("categoryBlock");
    }

    return root.getElementsByTagName("input");
};

/**
 * Sets the checked state of the checkboxes
 * @param {Boolean} checked true to check, false to uncheck
 */
CollectionTreeManager.prototype.setAllCheckBoxes = function(checked, simple)
{
    var nodes;

    if(typeof(simple) != "undefined")
    {
        nodes = this._getCheckboxElements(simple);
    }
    else
    {
        nodes  = this._getCheckboxElements();
    }

    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(simple)
{
    if(typeof(simple) != "undefined")
    {
        this.setAllCheckBoxes(false, simple);
    }
    else
    {
        this.setAllCheckBoxes(false);
    }
};

/**
 * Checks all checkboxes in the search form
 */
CollectionTreeManager.prototype.checkAll = function(simple)
{
    if(typeof(simple) != "undefined")
    {
        this.setAllCheckBoxes(true, simple);
    }
    else
    {
        this.setAllCheckBoxes(true);
    }


};

/**
 * Finds out if all of the checkboxes in the search form are checked
 * @return {Boolean} true if all the check boxes in the form are checked
 */
CollectionTreeManager.prototype.areAllChecked = function()
{
    var nodes = this._getCheckboxElements();
    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;
};

/**
 * Finds out if all of the checkboxes in the search form are checked
 * @return {Boolean} true if all the check boxes in the form are checked
 */
CollectionTreeManager.prototype.areAllSimpleChecked = function()
{
    var nodes = this._getCheckboxElements("_simple");
    if (!nodes)
    {
        return false;
    }

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

    return true;
};

/**
 * Finds out if any of the checkboxes in the search form are checked
 * @return {Boolean} true if any the check boxes in the form are checked
 */
CollectionTreeManager.prototype.areAnyChecked = function()
{
    var nodes = this._getCheckboxElements();
    if (!nodes)
    {
        return false;
    }

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

    return false;
};


/**
 * Extracts the collection id from a string that is the combination of category
 * id and collection id.
 * @param {String} value the string from which to extact the value
 * @return {String} the collection id
 */
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 {String} imageName the name of the image, to be used as the index
 * into the cache
 * @param {String} src the source of the image
 * @param {String} 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 {String} imgId the id of the image, accessible through document.images
 * @param {String} imgName the name of the image to retrieve the info from the
 * image cache
 */
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
 */
CollectionTreeManager.prototype.toggleSelect = function(id)
{
    var chkAllElement;
    var chkAllEleSimple;

    if(id == "all_simple")
    {
        chkAllEleSimple =  document.getElementById(id);
        if(chkAllEleSimple != null)
        {

            if(chkAllEleSimple.checked)
            {
                this.checkAll(true);
            }
            else
            {
                this.uncheckAll(true);
            }
        }
    }
    else
    {
        chkAllElement =  document.getElementById(id);
        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.
 * @param {Boolean} expandAllCategories true if all of the categories should be
 * expanded when the page is loaded.
 */
CollectionTreeManager.prototype.setupCategoryTree = function(expandAllCategories)
{
    var i;
    var initialCheckBoxIds;
    var simpleCollections = null;

    if (document.getElementById("all_simple") != null)
    {
        simpleCollections = true;
    }

    if (this.initialSelections.length === 0 || this.initialSelections[0] == "NONE")
    {
        this.uncheckAll();

        if(simpleCollections != null)
        {
           this.uncheckAll(true);
        }

    }
    else if (this.initialSelections[0] == "ALL")
    {
        this.checkAll();
        
        if(simpleCollections != null)
        {
           this.checkAll(true);
        }
    }
    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(CollectionTreeManager.noCollError);
            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 || expandAllCategories)
    {
        this.expandAll();
    }
};


