/**
 * Defines the FormChangeTracker object.  This object handles changes on a form
 * and keeps track as to whether any of the elements on the form have changed.
 *
 * @param formId the id of the form that is being tracked
 * @param changeListener
 */
function FormChangeTracker()
{
    this.dirty = false;
    this.listeners = [];
    this.ignoreChangeEvent = false;
    this.dirtyChangedErrorName = "<<uninitialized>>";
    this.dirtyChangedErrorMsg = "<<uninitialized>>";
}

/**
 * Adds a listener object to recieve the onDirtyChanged event. 
 * @param listener the object that will recieve the event
 */
FormChangeTracker.prototype.addListener = function(listener)
{
    this.listeners.push(listener);
};

/**
 * Attaches event handlers to the element in the form.
 */
FormChangeTracker.prototype.attachEventHandlers = function(formId)
{
    var formToCheck = document.getElementById(formId);
    var eles = formToCheck.elements;
    var i;
    var ele;
    var existingHandler;
    var instance = this;
    var tagName;

    for (i = 0; i < eles.length; ++i)
    {
        ele = eles[i];

        //Set tab order of elements
        ele.tabIndex = [i];

        tagName = ele.tagName.toLowerCase();

        if ((tagName == "input" && (ele.type == "submit" || ele.type == "reset" || ele.type == "button")) ||
            tagName == "button" || tagName == "fieldset")
        {
            // Don't do anything in this case.
        }
        else if (tagName == "input" && ele.type == "checkbox")
        {
            existingHandler = ele.onclick;

            if (!existingHandler)
            {
                ele.onclick = function()
                {
                    return function(e)
                    {
                        instance.setDirty();
                    };
                }();
            }
            else
            {
                ele.onclick = function(existingHandler)
                {
                    return function(e)
                    {
                        instance.setDirty();
                        existingHandler(e);
                    };
                }(existingHandler);
            }
        }

        // if this is a listpicker select element
        else if (ele.className == "listPicker_select")
        {
            // Get the object representing the list picker
            ListPicker.instances[ele.name].onchange = function()
            {
                return function()
                {
                    instance.setDirty();
                };
            }();
        }
        else if (ele.className == "listPicker_all")
        {
            // Ignore this  we don't want to monitor any events from these select boxes
        }
        else if ( (tagName == "input" && ele.type == "text" && !ele.readOnly) || tagName == "textarea")
        {
            existingHandler = ele.onkeydown;
            if (!existingHandler)
            {
                ele.onkeydown = function()
                {
                    return function(e)
                    {
                        var evt = e ? e : window.event;
                        if (evt.keyCode != 9)
                        {
                            instance.setDirty();
                        }
                    };
                }();
            }
            else
            {
                ele.onkeydown = function(existingHandler)
                {
                    return function(e)
                    {
                        var evt = e ? e : window.event;
                        if (evt.keyCode != 9)
                        {
                            instance.setDirty();
                        }
                        existingHandler(e);
                    };
                }(existingHandler);
            }
        }
        else
        {
            existingHandler = ele.onchange;

            if (!existingHandler)
            {
                ele.onchange = function()
                {
                    return function(e)
                    {
                        instance.setDirty();
                    };
                }();
            }
            else
            {
                ele.onchange = function(existingHandler)
                {
                    return function(e)
                    {
                        instance.setDirty();
                        existingHandler(e);
                    };
                }(existingHandler);
            }
        }
    }
};

/**
 * Fires the dirty changed event to any configured listeners
 */
FormChangeTracker.prototype.fireOnDirtyChanged = function()
{
    var idx;

    for (idx = 0; idx < this.listeners.length; ++idx)
    {
        if (typeof this.listeners[idx].onDirtyChanged == "undefined")
        {
            throw {
                name: this.dirtyChangedErrorName,
                message: this.dirtyChangedErrorMsg
            };
        }
        else
        {
            this.listeners[idx].onDirtyChanged(this.dirty);
        }
    }
};

/**
 * Sets the form tracker to clean
 */
FormChangeTracker.prototype.setClean = function()
{
    if (this.ignoreChangeEvent)
    {
        return;
    }

    this.dirty = false;
    this.fireOnDirtyChanged();
};

/**
 * Sets the form tracker to dirty
 */
FormChangeTracker.prototype.setDirty = function()
{
    if (this.ignoreChangeEvent)
    {
        return;
    }

    this.dirty = true;
    this.fireOnDirtyChanged();
};

/**
 * Returns whether the form is dirty or not
 */
FormChangeTracker.prototype.isDirty = function()
{
    return this.dirty;
};
