
// Namespace for Tse classes
var Tse = {};

// Usage:
// Tse.Log.error(str) - Displays an error message on current page
// Tse.Log.warn(str)  - Displays a warning message on current page
// Tse.Log.debug(str) - Displays a debug message on current page
// Tse.Log.show() - Show log messages
// Tse.Log.hide() - Hide log messages
Tse.Log = function() {
	// Private variables and methods
	var listId = 'Tse-console_list';
	var elementId = 'Tse-console_log';
	/**
	 * Internal funtion to add log entry
	 * @param {string} String to add
	 * @param {string} className used to represent severity
	 */
	function log(str,className) {
		if(!Element.visible(elementId)) {Element.show(elementId)};
		var d = new Date();
		var ds = (''+d.getFullYear()).substring(2) 
			+ _zeroPad((d.getMonth()+1)) 
			+ _zeroPad(d.getDate())
			+ ' '+ _zeroPad(d.getHours()) +':'+ _zeroPad(d.getMinutes()) +':'+ _zeroPad(d.getSeconds());
		$(elementId).insert({'top':'<div class="'+className+'">'+ ds+': '+str+'</div>'});
	}
	
	// utility method
	var _zeroPad = function(num) {
		var s = '0'+num;
		return s.substring(s.length-2);
	};
	
	// Public variables and methods
	return {
		/**
		 * Add error message
		 * @param {string} String to log
		 */
		error: function(str) {
			log(str,'Tse-error');
		},
		/**
		 * Add warningn message
		 * @param {string} String to log
		 */
		warn: function(str) {
			log(str,'Tse-warn');
		},
		/**
		 * Add debug message
		 * @param {string} String to log
		 */
		debug: function(str) {
			log(str,'Tse-debug');
		},
		/**
		 * Shows log entries
		 */
		show: function() {
			if(!Element.visible(listId)) {Element.show(listId)};		
		},
		/**
		 * Hides log entries
		 */
		hide: function() {
			if(Element.visible(listId)) {Element.hide(listId)};	
		},
		/**
		 * Toggles log entries
		 */
		toggle: function() {
			Element.toggle(listId);
		},
		/**
		 * Removes all log entries
		 */
		clear: function() {
			$('Tse-console_log').update('');
		}
	}
}();

// Class for popup-handling. Only one popup can be
// visible at a time.
Tse.Popup = function() {	
	// Private variables and methods
	var log = Tse.Log; // Logger
	var elementId = 'Tse_popup';
	var popupdrag = null; // Variable to keep the Draggable object
	function popupNotFound() {
		log.error('Popup-container missing! No element with id: '+elementId+' found.');
	}
	
	// Public variables and methods
	return {
		
		/**
		 * Usage:
		 * <a href="#" onclick="Tse.Popup.show('an_url'); return false;">Popup</a>
		 * <a href="#" onclick="Tse.Popup.show('an_url',{className:'myClass'}); return false;">Set class</a>
		 * <a href="#" onclick="Tse.Popup.show('an_url',{width:500}); return false;">Width 500</a>
		 * <a href="#" onclick="Tse.Popup.show('an_url',{width:500,height:500}); return false;">Width/height: 500</a>
		 * <a href="#" onclick="Tse.Popup.show('an_url',{callback: alert('Popup test')}); return false;">Popup with callback</a>
		 * 
		 * @param {String} url (Required). The popup is populated with the data from the url.
		 * @param {Object} options (Optional). Valid options are:
		 * 	width: width of popup in pixels, defaults to 200px
		 * 	height: height of popup in pixels, defaults to 300px
		 *  top: top position of popup, defaults to center of viewport - height/2
		 *  left: left position of popup, defaults to center of viewport - width/2
		 *  className: Class to use for container element, defaults to ''
		 * 	callback: function to call as callback
		 *	draggable: true if the pop up is to be draggable, false otherwise, defaults to true
		 *	handleId: used if the pop up is draggable, the id of the part of the pop up that is to be used to drag the pop up 
		 * 
		 */
		show: function(url,options) {
			if(!$(elementId)) {return popupNotFound();}

			options = options || {};
			options.width = options.width || '200';
			options.height = options.height || '300';
			options.draggable = options.draggable || true;
			options.handle = options.handle || 'Tse-drag_handle';
			popupdrag = null;
			var v = document.viewport.getDimensions();
			// To avoid problem with getDimensions() when in quirks mode
			if (v.height == 0) {
				v.height = document.body.clientHeight;
			}
			// To avoid problem with getDimensions() when in quirks mode
			if (v.width == 0) {
				v.width = document.body.clientWidth;
			}
			options.top = options.top || (v.height - options.height) / 2;
			options.left = options.left || (v.width - options.width) / 2;
			options.className = options.className || '';
			
			// Set positioning and dimensions
			Element.setStyle(elementId, {
				width: options.width+'px',
				height: options.height+'px',
				top: options.top+'px',
				left: options.left+'px'
			});		
			// Remove old classes and set new
			Element.classNames(elementId).set(options.className)
			// Update element
			var myAjax = new Ajax.Request(
				url, 
				{
					method: 'get',
					onComplete: function(xhr) {
						Element.update(elementId,xhr.responseText);
						Element.show(elementId);
						if(options.callback) {
							options.callback;
						}
						if(options.draggable) {
							popupdrag = new Draggable(elementId, {
								handle: options.handle, 
								starteffect: '', 
								endeffect: '',
								scroll: window
							});							
						}
					},
					onFailure: function() {
						log.error('Unable to display popup. url: ' + url);
					}
				});			
		},
		/**
		 * Hides popup layer
		 * Usage: <a href="#" onclick="Tse.Popup.hide(); return false;">Hide popup</a>
		 */
		hide: function() {
			if($(elementId)) {
				Element.hide(elementId);
				if (popupdrag != null) {
					popupdrag.destroy();
				}
			}
		}
	}
}();

/**
 * Class for creating tooltips for an html element. Handles local html and ajax-loaded html.
 * Requires prototype 1.6.0+
 * Example:
 * 	new Tse.Tooltip('myElementId',{id:'myTooltipId'});
 * 
 * @param {String/Element} el: Element or id of the element that triggers the tooltip
 * @param {Object} options. Options for the tooltip. Options:
 *  {String/Element} el: Element or id of the tooltip (i.e. to use an hidden element)
 *  {String} content: Content to use for the tooltip
 *  {String} url: Url to use for asynchronous load of content
 */
Tse.Tooltip = Class.create({
	initialize: function(el, options){
		this.el = $(el);
		this.initialized = false;
		this.setOptions(options);
		
		// Removing title from DOM element to avoid showing it
		this.content = this.el.title || this.options.content || '';
		if(this.content == '' && this.options.id) {
			this.content = $(this.options.id).innerHTML;
		}
		this.el.title = "";
		
		// Event handlers
		this.showEvent = this.show.bindAsEventListener(this);
		this.hideEvent = this.hide.bindAsEventListener(this);
		this.updateEvent = this.update.bindAsEventListener(this);
		Event.observe(this.el, "mouseover", this.showEvent );
		Event.observe(this.el, "mouseout", this.hideEvent );
	},
	setOptions: function(options) {
		this.options = {
			ajax: false,
			className: 'Tse-tooltip',
			offset: false,				// {x: 3, y:-10}
			delay: 250,
			maxWidth: 500,				// Max tooltip width
			mouseFollow: false	 		// Tooltips follows the mouse moving
		};
		Object.extend(this.options, options || {});
	},
	/**
	 * Displays the tooltip
	 */
	show: function(evt) {
		this.x = Event.pointerX(evt);
		this.y = Event.pointerY(evt);
		if(!this.initialized) {
			this.timeout = window.setTimeout(this.appear.bind(this), this.options.delay);
		}
	},
	/**
	 * Hide tooltip
	 */
	hide: function(evt) {
		if(this.initialized) {
			if (this.options.mouseFollow) {
				Event.stopObserving(this.el, "mousemove", this.updateEvent);
			}
			Element.remove(this.tooltip);
		}
		this._clearTimeout(this.timeout);
		
		this.initialized = false;	
	},
	update: function(evt){
		this.x = Event.pointerX(evt);
		this.y = Event.pointerY(evt);
		this.setup();
	},
	appear: function() {
		// Building tooltip container
		t = document.createElement('div');
		t.style.display = "none";
		t.className = this.options.className;
		t.innerHTML = this.content;
		this.tooltip = t;
		document.body.insertBefore(this.tooltip, document.body.childNodes[0]);
		
		if(Prototype.Browser.IE) {
			Element.extend(this.tooltip); // IE needs element to be manually extended
			this.options.width = this.tooltip.getWidth() + 2; // IE7 needs a little extra added , needs investigation
			this.tooltip.style.width = this.options.width + 'px'; // IE7 needs width to be defined
		} else {
			this.options.width = this.tooltip.getWidth(); 
			this.tooltip.style.width = this.options.width + 'px'; 
		}
		
		this.setup();
		
		if(this.options.mouseFollow) {
			Event.observe(this.el, "mousemove", this.updateEvent);
		}
		
		this.tooltip.style.display = "";
			
		this.initialized = true;
	},
	setup: function(){
		// If content width is more then allowed max width, set width to max
		if(this.options.width > this.options.maxWidth) {
			this.options.width = this.options.maxWidth;
			this.tooltip.style.width = this.options.width + 'px';
		}
			
		// Tooltip doesn't fit the current document dimensions
		if(this.x + this.options.width >= Element.getWidth(document.body)) {
			this.options.align = "right";
			this.x = this.x - this.options.width + 20;
		}
		
		this.tooltip.style.left = this.x - 7 + "px";
		this.tooltip.style.top = this.y + 12 + "px";
	},
	_clearTimeout: function(timer) {
		clearTimeout(timer);
		clearInterval(timer);
		return null;
	}
});

// Utility class to be used for general functions that are used in many places
Tse.Util = function() {
	// Id seed used to generate unique id's
	var idSeed = 0;
	
	// Public variables and methods
	return {
		yesString: 'Ja',
		noString: 'Nej',
		oddRowClass: 'Tse-odd_row',
		evenRowClass: 'Tse-even_row',
	
		/**
		 * Generates unique ids. If the element already has an id, it is unchanged 
         * @param {Mixed} el (optional) The element to generate an id for
         * @param {String} prefix (optional) Id prefix (defaults "ext-gen")
         * @return {String} The generated Id.
		 */
		id: function(el, prefix) {
            prefix = prefix || "Tse-gen";
            el = $(el);
            var id = prefix + (++idSeed);
            return el ? (el.id ? el.id : (el.id = id)) : id;
		},
	
		// Returns the correct css class depending on if it is an odd or even row
		getRowClass: function (index) {
			if(index % 2 == 0){
				return this.evenRowClass;
			} else {
				return this.oddRowClass;
			}   
		},
					
		// Returns yesString if true and noString if false, used when you need to
		// present the boolean as a string value
		getBooleanAsString: function (bln) {			
			if(bln) {
				return this.yesString;
			} else {
				return this.noString;
			}
		}
	}
}();


