/*
 *  Copyright 2009 Genius.com, Inc
 *  
 *  Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
 *      
 *  Unless required by applicable law or agreed to in writing, software 
 *  distributed under the License is distributed on an "AS IS" BASIS, 
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
 *  See the License for the specific language governing permissions and 
 *  limitations under the License. 
 */

GeniusScript = {};
GeniusScript.core = {};
GeniusScript.core.eventHash = [];

/**
 * Detect if an el has a className assigned
 * @param {Object/HTMLElement} el the element to operate on
 * @param {String} className the class name to find
 * @return {Boolean} true if the className was part of 
 *         the CSS classNames assigned to the passed in el
 */
GeniusScript.core.hasClass = function(el, className)
{
    // Wrap in spaces so that we can for sure make sure our class isn't
    // part of another class by doing a simple indexOf.
    var elClass = ' ' + el.className + ' ';
    return (elClass.indexOf(' ' + className + ' ') > -1);
};

/**
 * Add a className to the passed in el, if not found
 * @param {Object/HTMLElement} el the element to operate on
 * @param {String} className the class name to add
 */
GeniusScript.core.addClass = function(el, className)
{
    if (!GeniusScript.core.hasClass(el, className))
    {
        var spacer = '';
        if (el.className.length > 0)
        {
            spacer = ' ';
        }
        el.className += spacer + className;
    }
};

/**
 * Remove a className from the passed in el, if found
 * @param {Object/HTMLElement} el the element to operate on
 * @param {String} className the class name to remove
 */
GeniusScript.core.removeClass = function(el, className)
{
    if (GeniusScript.core.hasClass(el, className))
    {
        // add spaces to match whole words only, skipping regex's
        var elClassName = ' ' + el.className + ' ';
        var searchClassName = ' ' + className + ' ';
        
        var classNameStart = elClassName.indexOf(searchClassName);
        // Compute and adjust classNameEnd to compensate for 'length' not being 0 based.
        var classNameEnd = classNameStart + searchClassName.length - 1;
        // Get everything before our class and after.
        elClassName = elClassName.substring(0, classNameStart) + ' ' + elClassName.substring(classNameEnd + 1);
        // clean up the space added above
        if (elClassName.charAt(0) == ' ')
        {
            elClassName = elClassName.substring(1);
        }
        if (elClassName.charAt(elClassName.length - 1) == ' ')
        {
            elClassName = elClassName.substring(0, elClassName.length - 1);
        }
        el.className = elClassName;
    }
};

/**
 * Handle a browser event, by passing the event to the correct
 * previously registered handler for that event/object combination
 * @private
 * @param {Object/EventObject} the browser event object
 */
GeniusScript.core.handleEvent = function(eventObj)
{
    if (!eventObj)
    {
        eventObj = window.event;
    }
    if (GeniusScript.core.eventHash && 
        GeniusScript.core.eventHash[this.geniusEventID] && 
        GeniusScript.core.eventHash[this.geniusEventID][eventObj.type])
    {
        var eventHandlers = GeniusScript.core.eventHash[this.geniusEventID][eventObj.type];
        var len = eventHandlers.length;
        var retVal = true;
        for (var i = 0; i < len; i++)
        {
            retVal = retVal && eventHandlers[i](eventObj);
        }
    }
    
    return retVal;
}

/**
 * Add an event to the passed in el
 * @param {Object/HTMLElement} el the element to operate on
 * @param {String} className the class name to remove
 */
GeniusScript.core.addEvent = function(el, eventName, handlerFn)
{
    if (!el.geniusEventID)
    {
        el.geniusEventID = GeniusScript.core.eventHash.length;
        GeniusScript.core.eventHash[el.geniusEventID] = {};
    }
    if (!GeniusScript.core.eventHash[el.geniusEventID][eventName])
    {
        GeniusScript.core.eventHash[el.geniusEventID][eventName] = [];
    }
    GeniusScript.core.eventHash[el.geniusEventID][eventName].push(handlerFn);
    
    // cross-browser attach
    if (el.addEventListener)
    {
        el.addEventListener(eventName, GeniusScript.core.handleEvent, false);
    }
    else if (el.attachEvent)
    {
        el.attachEvent("on"+eventName, GeniusScript.core.handleEvent);
    }
    else
    {
        return false;
    }
};

/**
 * Stop an event from propigating, bubbling, performing the default action, etc.
 * @param {Event} eventObj The event object.
 */
GeniusScript.core.stopEvent = function(eventObj)
{
    if (eventObj.stopPropagation)
    {
        eventObj.stopPropagation();
    }
    if (eventObj.preventDefault)
    {
        eventObj.preventDefault();
    }
    eventObj.cancelBubble = true;
    eventObj.returnValue = false;
};

/**
 * Will return the value of a checkbox as a boolean "checked" or "unchecked",
 * where checked means the box was checked
 * @param {HTMLElement} checkboxEl The checkbox HTML object
 */
GeniusScript.core.getCheckboxValueAsString = function(checkboxEl)
{
    if (checkboxEl.checked == true)
    {
        return "checked";
    }
    return "unchecked";
};