/*
	TANDBERG twidgets javascript library
*/

/**
 * Base twidgets class with methods for initializing the framework and widgets.
 * @class
 * @static
 */
var twidgets = {
    _requiredModules: ['tutil'],
    _modules: ['collapsible', 'tooltip', 'popup', 'watermark', 'breadcrumb', 'actiondropdown', 'linkpanel', 'menu', 'tab', 'grid', 'treeview', 'searchfield', 'help', 'table', 'feedback', 'autocompleter'],
    _widgetInitializer: null,

    /**
    * The URL of the orbit directory. Set when loading the library.
    */
    baseUrl: '',

    /**
    * True if the current browser is IE6.
    */
    IE6: false,

    /**
    * The stylesheet version
    */
    CSSVersion: 1,

    /**
    * Loads the twidgets framework and all dependencies. Called when the script is loaded.
    */
    load: function() {
        console.info('loading twidgets...');

        // hack to avoid the horrible IE6 image flickering - http://www.mister-pixel.com/#Content__state=is_that_simple
        try { document.execCommand("BackgroundImageCache", false, true); } catch (err) { }

        var scripts = document.getElementsByTagName('head')[0].getElementsByTagName('script');
        if (scripts.length <= 0) {
            scripts = document.getElementsByTagName('script');
        }

        var initialized = false;
        $A(scripts).findAll(function(elem) {
            return elem && elem.src && (/.*\/twidgets.*\.js.*/.test(elem.src));
        }).each(function(elem) {
            if (!initialized) {
                initialized = true;
                twidgets.baseUrl = elem.src.substring(0, elem.src.lastIndexOf('scripts/twidgets'));                
                if (elem.src.indexOf('twidgets.js') !== -1) {
                    // get the modules that are supposed to be loaded
                    var modules = twidgets._getModules(elem.src);

                    // load all modules
                    $A(modules).each(function(module) {
                        document.write('<script type="text/javascript" src="' + twidgets.baseUrl + 'scripts/twidgets/' + module + '.js' + '"></script>');
                    });
                }
            }
        });

        // determine the CSS version
        $A(document.getElementsByTagName('link')).each(function(elem) {
            if (elem.href && elem.href.indexOf('styles-v2.css') != -1) {
                twidgets.CSSVersion = 2;
            }
        });

        this.IE6 = (Prototype.Browser.IE && navigator.userAgent.charAt(navigator.userAgent.indexOf('MSIE') + 5) < 7);
    },

    /**
    * Initializes all the widgets on the page, or all the children of a specified node.
    * @param {DOM Element} [node]	If specified, don't init the whole page, but only the children of the specified node.
    */
    initWidgets: function(node) {
        var that = this;
        this._getBySelector(node, 'input.textbox').each(function(elem) {
            that._attachEventHandlers(elem, 'textbox');
        });
        this._getBySelector(node, 'input.button').each(function(elem) {
            that._attachEventHandlers(elem, 'button');
        });
        this._getBySelector(node, 'textarea.textarea').each(function(elem) {
            that._attachEventHandlers(elem, 'textarea');
        });
        this._getBySelector(node, 'select.dropdown').each(function(elem) {
            that._attachEventHandlers(elem, 'dropdown');
        });
        this._getBySelector(node, 'div.collapsible').each(function(elem) {
            new twidgets.Collapsible(elem, { 'persistState': elem.hasClassName('persistState') });
        });
        this._getBySelector(node, 'div.actiondropdown').each(function(elem) {
            new twidgets.ActionDropdown(elem);
        });
        this._getBySelector(node, 'span.errorMessage').each(function(elem) {
            Effect.Pulsate(elem, { 'pulses': 1, 'duration': 0.5 });
        });
    },


    /* private */

    _getModules: function(scriptSrc) {
        var modules = scriptSrc.match(/\?.*load=([a-z,]*)/);
        modules = (modules && modules.length == 2) ? twidgets._modules = modules[1].split(',') : twidgets._modules;
        return twidgets._requiredModules.concat(modules);

    },

    _attachEventHandlers: function(elem, tag) {
        Event.observe(elem, "mouseover", this._mouseOverHandler.bindAsEventListener(this, tag));
        Event.observe(elem, "mouseout", this._mouseOutHandler.bindAsEventListener(this, tag));

        // special treatment of certain elements
        switch (tag) {
            case 'textbox':
            case 'textarea':
            case 'dropdown':
                Event.observe(elem, "focus", this._focusHandler.bindAsEventListener(this, tag));
                Event.observe(elem, "blur", this._blurHandler.bindAsEventListener(this, tag));
                break;

            case 'button':
                Event.observe(elem, "mousedown", this._mouseDownHandler.bindAsEventListener(this, tag));
                Event.observe(elem, "mouseup", this._mouseUpHandler.bindAsEventListener(this, tag));
                Event.observe(elem, "click", function() {
                    if (Element.hasClassName(this, 'disable-on-click')) {
                        this.disabled = 'disabled';
                        var form = elem.up('form');
                        if (form) {
                            Form.getInputs(form).each(function(child) {
                                var type = child.type;
                                if (type && (type === 'button' || type === 'submit')) {
                                    child.disabled = 'disabled';
                                }
                            })
                        }
                    }
                });
                break;
        }

    },
    _getBySelector: function(node, cssRule) {
        if (node) {
            return $(node).getElementsBySelector(cssRule);
        }
        else {
            return $$(cssRule);
        }
    },

    /* event handlers */

    _mouseOverHandler: function(evt, tag) {
        var target = Event.element(evt);
        if (!this._isDisabled(evt)) {
            if (!Element.hasClassName(target, tag + '-focus')) {
                this._setClassName(evt, tag, tag + '-hover');
            }
        }
    },
    _mouseOutHandler: function(evt, tag) {
        var target = Event.element(evt);
        if (!this._isDisabled(evt)) {
            if (!Element.hasClassName(target, tag + '-focus')) {
                this._setClassName(evt, tag, tag);
            }
        }
    },
    _focusHandler: function(evt, tag) {
        if (!this._isDisabled(evt)) {
            this._setClassName(evt, tag, tag + '-focus');
        }
    },
    _blurHandler: function(evt, tag) {
        if (!this._isDisabled(evt)) {
            this._setClassName(evt, tag, tag);
        }
    },
    _mouseDownHandler: function(evt, tag) {
        if (!this._isDisabled(evt)) {
            this._setClassName(evt, tag, tag + '-focus');
        }
    },
    _mouseUpHandler: function(evt, tag) {
        if (!this._isDisabled(evt)) {
            this._setClassName(evt, tag, tag + '-hover');
        }
    },

    _isDisabled: function(evt) {
        var target = Event.element(evt);
        return target.disabled;
    },

    _removeClassName: function(evt, tag) {
        var elem = Event.element(evt);
        Element.removeClassName(elem, tag);
        Element.removeClassName(elem, tag + '-hover');
        Element.removeClassName(elem, tag + '-focus');
    },

    _setClassName: function(evt, tag, className) {
        this._removeClassName(evt, tag);
        Element.addClassName(Event.element(evt), className);
    }
}

twidgets.load();



/*
	OnLoad stuff
*/
Event.observe(window, 'load', function() {
	twidgets.initWidgets();
	// remove the loader when the page has loaded...
	var elem = $('__initLoader');
	if (elem) {
		try {
			elem.parentNode.removeChild(elem);
		}
		catch (ex) {
			console.log("Unable to remove loader, attempting to hide", ex);
			if (elem.style) {
				elem.style.display = 'none';
			}
		}
	}
	console.info('page loaded...');
});




/*
	prototype extensions
*/

/**
 * Position the element in the center of the screen
 * @param {DOM Element} element The element to position
 */
Position.center = function(element) {
	element = $(element);
	Position.prepare();
   	var d = Element.getDimensions(element);
    var ws = Position.getWindowSize();
    element.style.top = (ws.height / 2) - (d.height / 2) -  Position.deltaY + "px";
    element.style.left = (ws.width / 2) - (d.width / 2) -  Position.deltaX + "px";
}

/**
 * Returns the size of the window
 */
Position.getWindowSize = function() {
	var w = window;
	var width = w.innerWidth || (w.document.documentElement.clientWidth || w.document.body.clientWidth);
	var height = w.innerHeight || (w.document.documentElement.clientHeight || w.document.body.clientHeight);
	return {'width': width, 'height': height};
}








/*
	Options
*/

/**
 * Helperclass for parsing option objects which are used for optional parameters to widget constructors.
 * <pre>
 * var MyClass = function(options) {
 * 	options = new twidgets.Options(options);
 * 	if (options.exist('myOption')) {
 * 		this._myOption = options.get('myOption');
 * 	}
 * 	...
 * }
 * var mc = new MyClass({
 * 	'myOption': 'Hello World!'
 * });
 * </pre>
 * @param {Object} options The options object
 * @class
 */
twidgets.Options = Class.create();
twidgets.Options.prototype = {
	
	/**
	 * @ignore
	 */
	initialize: function(options) {
		this._options = options || {};
	},
	
	/* public */
	
	/**
	 * Get the optional argument with the given key
	 * @param {String} key The key 
	 * @return {String}	The option value, or Null
	 */
	get: function(key) {
		if (this._options[key]) {
			return this._options[key];
		}
		else if (tutil.isString(this._options[key]) && this._options[key] == '') {
			return '';
		}
		else if (tutil.isNumber(this._options[key]) && this._options[key] == 0) {
			return 0;
		}
		else if (tutil.isBoolean(this._options[key]) && this._options[key] == false) {
			return false;
		}
		else {
			return null;
		}
	},
	
	/**
	 * Check if an optional argument is specified
	 * @param {String}	key	The key
	 * @return {Boolean}	True, if the option is specified, otherwise False.
	 */
	exists: function(key) {
		return this.get(key) != null;
	}
}







/**
 * The dropshadow will attach to any element, and render as a dropshadow beneath the element.
 * @class
 * @param {Object}	[parent]	DOM id or reference to the parent element.
 */
twidgets.DropShadow = Class.create();
twidgets.DropShadow.prototype = {
	
	/* constants */
	
	BORDER_WIDTH: 3,
	BORDER_OPACITY: 0.3,
	
	/* ctor */
	
	/**
	 * @ignore
	 */
	initialize: function(parent) {
		this._parent = $(parent);
		if (!this._parent) {
			console.warn('Unable to locate node', parent);
			return;
		}
	},
	
	/* public */
	
	/**
	 * Shows the drop shadow
	 * @param {Object}	[parent]	DOM id or reference to the parent element. Not required if it was passed to the ctor when created.
	 */
	show: function(parent) {
		if (!this._shadow) {
			this._shadow = this._createShadow();
		}
		if (parent) {
			this._parent = $(parent);
		}
		if (!this._parent) {
			throw('Cannot show Drop Shadow when parent is not set...');
			console.error('Cannot show Drop Shadow when parent is not set...');
			return;
		}
		this._shadow.style.zIndex  = (this._parent.style.zIndex > 0) ? this._parent.style.zIndex - 1 : 1;
		this.updatePosition();
		Element.show(this._shadow);
	},
	
	/**
	 * Hides the drop shadow
	 */
	hide: function() {
		if (this._shadow) {
			Element.hide(this._shadow);
		}
	},
	
	/*
	 * Updates the position of the dropshadow
	 * */
	updatePosition: function() {
		if (!this._shadow) {
			this._shadow = this._createShadow();
		}
		try {
			Position.clone(this._parent, this._shadow, {
				offsetLeft: this.BORDER_WIDTH, offsetTop: this.BORDER_WIDTH
			});
		} catch (ex) {
			console.log(ex);
		}
	},
	
	/* private */
	
	_createShadow: function() {
		var div = document.createElement('div');
		div.innerHTML = '&nbsp;'
		div.className = 'dropShadow';
		div.style.display = 'none';
		this._parent.parentNode.appendChild(div);
		$(div).setStyle({
			'opacity': this.BORDER_OPACITY
		});
		return $(div);
	}
}
