/**
 * @fileOverview A collection of classes and functions for our projects.
 * Is shipped with MCC
 * @name Kupferwerk standard JS library
 * @author Tobias Kreß, kress@kupferwerk.com
 * @version 1.0
 */
var kupferwerk = kupferwerk || {};
kupferwerk.currentAuthToken = '';

/**
 * @class Kupferwerk is an abstract base class and provides
 * some standard functionalities to subclasses
*/
var KWStandard = Class.create({
	/**
	 * @constructor
	 */
	initialize: function() {
		this.version = '1.0';
		this.ajax_request = false;
	},
	
	/**
	 * Returns the extended DOM element with the ID given by value
	 * or, if undefined, given by default_value
	 * @param {html_object} element
	 * @param {html_object} default_element
	 * @return {html_object} Returns an html element
	*/
	defaultElement: function(element, default_element) {
		return $(element) || $(default_element);
	},
	
	/**
	 * Returns the string given by value
	 * or, if undefined, given by default_value
	 * @param {object} value
	 * @param {object} default_value
	 * @return {html_object} Returns an object
	*/
	defaultValue: function(value, default_value) {
		return element || default_element;
	},
	
	/**
	 * the current auth token from the gloal js api pool
	 * you need to post this with every post request as parameter authenticity_token
	 * @return {string} the current authenticity_token, which must be sent with every post request
	 */
 	currentAuthToken: function() {
 		return kupferwerk.auth_token || auth_token;
 	},
	
	/**
	 * Generates a new password
	 * @return {string} Password
	 */
	generatePassword: function(length, characters) {
		source_characters = characters || '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
		string = '';

		(length).times(function(i) {
			string = string + source_characters.charAt(Math.round(Math.random() * source_characters.length));
		});

		return string;
	},
	
	/**
	 * Checks whether a variable is a function or not
	 * @return {boolean} true/false
	 */
	callIfFunction: function(call_function, request) {
		if(call_function && Object.isFunction(call_function)) {
			call_function(request);
			return true;
		} else {
			return false;
		}
	}
});



/**
 * Provides an overlay with AJAX-Content
 * @class Scalable overlay for AJAX content
*/
var Overlay = Class.create(KWStandard, {
	/**
	 * var overlay = new Kupferwerk.Overlay(); to open the overlay.
	 * @param {string} url URL to an action which renders the popup
	 * @param {hash} options
	 * @constructor
	*/
	initialize: function(url, options) {
		this.options = options || {};

		if(!$('kupferwerk_overlay')) {
			if(this.options.template)
				$$('body').first().insert(this.options.template);
			else
				$$('body').first().insert('<div id="kupferwerk_overlay" style="display: none;"><div id="kupferwerk_overlay_box"><div><div><div><div><div><div><div><div><img id="kupferwerk_overlay_icon" src="/images/mcc/icons/close.png" alt="Close" title="Close this window" /><div id="kupferwerk_overlay_box_content" class="clearfix"></div></div></div></div></div></div></div></div></div></div></div>');
		}
		
		this.overlay = $('kupferwerk_overlay');
		this.overlay_box = $('kupferwerk_overlay_box');
		this.overlay_content = $('kupferwerk_overlay_box_content');
		this.overlay_close_icon = $('kupferwerk_overlay_icon');
				
		this.closeIcon();

		ajax_options = $H({
			evalScripts: true,
			onComplete: function(request) {
				this_overlay.overlay_content.update(request.responseText);
				this_overlay.center();
			}
		});
		
		if(this.options['request']) {
		  ajax_options = ajax_options.merge($H(this.options['request']));
		}
		new Ajax.Request(url, ajax_options.toObject());
		
		this_overlay = this;
		this.resize_observer = Event.observe(window, 'resize', function() {
			this_overlay.center();
		});
		
		this.show();
		
		return false;
	},
	
	/**
	 * Changes the close icon if options.close_icon is defined
	 * and provides close-funcionality to this icon
	 */
	closeIcon: function() {
		if(this.options.close_icon) {
			this.overlay_close_icon.src = this.options.close_icon;
		}
		
		this_overlay = this;
		this.overlay_close_icon.observe('click', function(event) {
			this_overlay.close();
		});
	},
	
	/*
	 * Displays overlay
	 * @private
	 */
	show: function() {
		this.overlay.setStyle({
			height: $$('body').first().getHeight() + 'px'
		}).show();
	},
	
	/*
	 * Centers overlay in viewport
	 * @private
	 */
	center: function() {
		if(this.overlay_box.getStyle('position') != 'absolute') {
			this.overlay_box.setStyle({
				position: 'absolute'
			});
			
			this.setPosition().defer();
		} else {
			this.setPosition();
		}
		
		this.overlay.setStyle({
			height: document.viewport.getHeight() + 'px'
		});
	},
	
	/*
	 * Hides overlay
	 * @private
	 */
	close: function() {
		this.resize_observer.stop();
		this.overlay.hide();
		this.overlay_content.update(' ');
	},
	
	setPosition: function() {
		this.overlay_box.setStyle({
			top: this.positionTop() + 'px',
			left: this.positionLeft() + 'px'
		});
	},
	
	/*
	 * Returns the centered position from top of the document
	 * @return {integer} Top position
	 * @private
	 */
	positionTop: function() {
		this.position_top = ((document.viewport.getHeight() - this.overlay_box.getHeight()) / 2) + document.viewport.getScrollOffsets().top;
		if(this.position_top < 10) {
			this.position_top = 10;
		}
		
		return this.position_top;
	},
	
	/*
	 * Returns the centered position from left of the document
	 * @return {integer} Left position
	 * @private
	 */
	positionLeft: function() {
		this.position_left = ((document.viewport.getWidth() - this.overlay_box.getWidth()) / 2) + document.viewport.getScrollOffsets().left;
		return this.position_left;
	}
});



/**
 * Browser switch
 * new BrowserSwitch.acceptBrowser(); with an array (or string) of allowed browsers
 * Codes of most used browsers:
 * ie6 - Internet Explorer 6
 * ie7 - Internet Explorer 7
 * f15 - Firefox 1.5
 * f20 - Firefox 2.0
 * op8 - Opera 8
 * op8 - Opera 9
 * kq2 - Safari/Konquerer 2
 * sf3 - Safari 3
 * @class Browser Switch
*/
var BrowserSwitch = Class.create(KWStandard, {
	
	/**
	 * What browser do you have?
	 * @return {array} Returns an array with shortcut and full name of used browser
	 * @constructor
	*/
	initialize: function() {
		this.my_browser = [];
		if(document.ids) {
			this.my_browser = ['nc4', 'Netscape Navigator 4'];
			if(!window.navigator.securityPolicy) this.my_browser[1] += '.0'; else this.my_browser[1] += '.5-4.8';
		}
		else if(document.all && !$) {
			if(!document.layers) this.my_browser = ['ie4', 'Internet Explorer 4']; else this.my_browser = ['ow4', 'OmniWeb 4.x'];
		}
		else if(window.opera && !document.createElement) this.my_browser = ['op5', 'Opera 5'];
		else if(window.opera && window.getComputedStyle) {
			if(window.getSelection) this.my_browser = ['op9', 'Opera 9'];
			else if(document.createRange) this.my_browser = ['op8', 'Opera 8'];
			else if(window.navigate) this.my_browser = ['op75', 'Opera 7.5']; else this.my_browser = ['op72', 'Opera7.2'];
		}
		else if(window.opera && document.compatMode) this.my_browser = ['op7', 'Opera 7'];
		else if(window.opera && document.releaseEvents) this.my_browser = ['op6', 'Opera 6'];
		else if(document.contains && !window.opera) {
			this.my_browser = ['kq3', 'Safari / Konqueror 3'];
			this.my_browser[1] += window.print ? '.1/.2' : '.0';
			if(document.compatMode) this.my_browser[1] = 'kq3.4';
		}
		else if(window.pkcs11 && window.XML) this.my_browser = window.external ? ['f20', 'Firefox 2 - Gecko'] : ['f15', 'Firefox - Gecko Deer Park '];
		else if(window.pkcs11 && document.compatMode) this.my_browser = ['nn7', 'Mozilla - Firefox - Gecko '];
		else if(window.atob && document.defaultCharset) this.my_browser = ['sf3', 'Safari 3'];
		else if(window.getSelection && window.atob) this.my_browser = ['nn7', 'Mozilla - Gecko'];
		else if(window.getSelection && !document.compatMode) this.my_browser = ['nn6', 'Netscape 6 - Mozilla Beta'];
		else if(window.clipboardData && document.compatMode) {
			this.my_browser = window.XMLHttpRequest ? 7 : 6;
			this.my_browser = ['ie' + this.my_browser, 'Internet Explorer ' + this.my_browser];
		}
		else if(window.clipboardData) {
			this.my_browser = ['ie5', 'Internet Explorer 5.0']; 
			if(!document.createDocumentFragment) this.my_browser = ['ie5.5', 'Internet Explorer 5.5'];
		}
		else if(document.doctype && !window.print ) this.my_browser = ['ie5m', 'Internet Explorer 5Mac'];
		else if($ && !document.all) {
			this.my_browser[0] = 'op4';
			this.my_browser[1] = 'Opera 4';
			if(!window.RegExp) this.my_browser[1] += '.0'; else this.my_browser[1] += '.1';
		}
		else if(document.images && !document.all) this.my_browser = ['nn3', 'Netscape Navigator 3'];
		else if(!document.images) this.my_browser = ['2-3', 'NS 2, IE 3'];
		else if(document.clientWidth && !window.RegExp) this.my_browser = ['kq2', 'Safari - Konqueror 2'];
		else this.my_browser = ['???', 'undefined'];
	},

	/**
	 * 
	 * @param {array} accepted_browsers Array of accepted browsers: %w(f15 f20 sf3)
	 * @return {hash} Returns an hash with .accepted => true/false, .browser_code and .browser_name
	*/
	acceptBrowser: function(accepted_browsers) {
		if(accepted_browsers.include(this.my_browser[0])) {
			this.accepted = true;
			this.browser_code = this.my_browser[0];
			this.browser_name = this.my_browser[1];
		}	else {
			this.accepted = false;
			this.browser_code = this.my_browser[0];
			this.browser_name = this.my_browser[1];
		}
		
		return {accepted: this.accepted, browser_code: this.browser_code, browser_name: this.browser_name};
	}
});



/**
 * strftime for prototype date object 
 */
Object.extend(Date.prototype, {
  strftime: function(format) {
    var day = this.getDay(), month = this.getMonth();
    var hours = this.getHours(), minutes = this.getMinutes();

    function pad(num) {
			return num.toPaddedString(2);
		};

    return format.gsub(/\%([aAbBcdHImMpSwyY])/, function(part) {
      switch(part[1]) {
        case 'a': return $w("Sun Mon Tue Wed Thu Fri Sat")[day]; break;
        case 'A': return $w("Sunday Monday Tuesday Wednesday Thursday Friday Saturday")[day]; break;
        case 'b': return $w("Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec")[month]; break;
        case 'B': return $w("January February March April May June July August September October November December")[month]; break;
        case 'c': return this.toString(); break;
        case 'd': return pad(this.getDate()); break;
        case 'H': return pad(hours); break;
        case 'I': return pad((hours + 12) % 12); break;
        case 'm': return pad(month + 1); break;
        case 'M': return pad(minutes); break;
        case 'p': return hours > 12 ? 'PM' : 'AM'; break;
        case 'S': return pad(this.getSeconds()); break;
        case 'w': return day; break;
        case 'y': return pad(this.getFullYear() % 100); break;
        case 'Y': return this.getFullYear().toString(); break;
				default: break;
      }
    }.bind(this));
  }
});