
/*
 * Copyright (C) 2010/2011 Im-At-Home BV
 * All Rights Reserved
 * No copying, duplication or replication of code permitted without
 * express permission of Im-At-Home BV
 * 
 */

Hashtable = function(retNoString) {
	if ((retNoString==null) || (retNoString=='undefined')) retNoString = false;
	this.init(retNoString);
};
		
$.extend(Hashtable.prototype, {	
	array : new Array(),
	retString : false,
	__keys : null,
	init : function(retNoString) {
		this.retString = retNoString;
		this.clear();
	},	
	count : function() {
		return this.array.length;
	},
	pop : function() {
		var top = this.array.pop();		
		this.__keys = null;
		return top.value;
	},
	clear : function() {
		this.array = null; // force garbage collection...
		this.array = new Array();
		this.__keys = null;		
	},		
	exists : function(key) {
		return (this.indexof(key) !=-1);
	},
	indexof : function(key) {
		return this.keys().indexOf(key);
	},	
	itemat : function(index) {
		if ((index >= 0) && (index < this.array.length)) {
			return this.array[index].value;
		}
		return null;
	},
	rawat : function(index) {
		if ((index >= 0) && (index < this.array.length)) {
			return this.array[index];
		}
		return null;		
	},
	add : function(key, value) {
		var index = this.indexof(key);
		if (index==-1) {
			this.array.push({'key':key,'value':value});
			this.__keys = null;
		} else {
			this.array[index].value = value;
		}
		return true;
	},
	get : function(key, def) {
		var keys = this.keys();
		if ((keys != null) && (keys.length>0)) { 
			index = keys.indexOf(key);
			if (index != -1) return this.array[index].value;			
		}
		if ((def != 'undefined') && (def != null) && (def != '')) return def;		
		return (this.retString) ? '??'+key+'??' : null;
	},
	remove : function(key) {
		index = this.indexof(key);
		if (index != -1) {
			this.array.splice(index,1);
			this.__keys = null;			
			return true;
		}
		return false;
	},
	values : function() {
		var out = new Array();
		var arraysize = this.array.length;
		if (arraysize==0) return out;
		var counter = 0;
		do {
			out.push(this.array[counter].value);
		} while (++counter < arraysize);
		return out;		
	},
	keys : function() {
		if (this.__keys != null) return this.__keys;
		var out = new Array();
		var arraysize = this.array.length;
		if (arraysize==0) return out;
		var counter = 0;
		do {
			out.push(this.array[counter].key);
		} while (++counter < arraysize);
		this.__keys = out;
		return this.__keys;
	},
	list : function() {
		return this.array;
	}			
});

jQuery.fn.extend({
    disableSelection : function() {
            this.each(function() {
                    this.onselectstart = function() { return false; };
                    this.unselectable = "on";
                    jQuery(this).css('user-select', 'none'); 
                    jQuery(this).css('-o-user-select', 'none'); 
                    jQuery(this).css('-moz-user-select', 'none'); 
                    jQuery(this).css('-khtml-user-select', 'none'); 
                    jQuery(this).css('-webkit-user-select', 'none');                    
            });
            return this;
    }
});

String.prototype.guid = function() {
	var result, i, j;
	result = '';
	for(j=0; j<32; j++) {
		if( j == 8 || j == 12|| j == 16|| j == 20) result = result + '-';
		i = Math.floor(Math.random()*16).toString(16).toUpperCase();
		result = result + i;
	}
	return result;
};

Date.MONTH_NAMES = [
"January", "February", "March",
"April", "May", "June",
"July", "August", "September",
"October", "November", "December" ];

// Static definition of weekday names
Date.WEEKDAY_NAMES = [
"Sunday", "Monday", "Tuesday",
"Wednesday", "Thursday", "Friday",
"Saturday" ];

// clone the current date object and return a different object with identical value
Date.prototype.clone = function () {
  return new Date(this.getTime());
};

// clear the time information from this date and return it
Date.prototype.clearTime = function () {
  this.setHours(0); this.setMinutes(0);
  this.setSeconds(0); this.setMilliseconds(0);
  return this;
};

Date.prototype.getDaysInMonth = function() {
	var m = [31,28,31,30,31,30,31,31,30,31,30,31];
	var today = new Date(this);
	if (today.getMonth() != 1) return m[today.getMonth()];
	if (today.getFullYear()%4 != 0) return m[1];
	if (today.getFullYear()%100 == 0 && today.getFullYear()%400 != 0) return m[1];
	return m[1] + 1;
};

Date.prototype.getMonthStartsOn = function() {
	var today = new Date(this);
	today.setDate(1);
	return today.getDay();
};

// return the last day of this month
Date.prototype.lastDay = function () {
  var tempDate = this.clone();
  tempDate.setMonth(tempDate.getMonth()+1);
  tempDate.setDate(0);
  return tempDate.getDate();
};

Date.prototype.getWeek = function (dowOffset) {
/*getWeek() was developed by Nick Baicoianu at MeanFreePath: http://www.meanfreepath.com */
	dowOffset = typeof(dowOffset) == 'int' ? dowOffset : 0; //default dowOffset to zero
	var newYear = new Date(this.getFullYear(),0,1);
	var day = newYear.getDay() - dowOffset; //the day of week the year begins on
	day = (day >= 0 ? day : day + 7);
	var daynum = Math.floor((this.getTime() - newYear.getTime() - 
	(this.getTimezoneOffset()-newYear.getTimezoneOffset())*60000)/86400000) + 1;
	var weeknum;
	//if the year starts before the middle of a week
	if(day < 4) {
		weeknum = Math.floor((daynum+day-1)/7) + 1;
		if(weeknum > 52) {
			nYear = new Date(this.getFullYear() + 1,0,1);
			nday = nYear.getDay() - dowOffset;
			nday = nday >= 0 ? nday : nday + 7;
			/*if the next year starts before the middle of
 			  the week, it is week #1 of that year*/
			weeknum = nday < 4 ? 1 : 53;
		}
	}
	else {
		weeknum = Math.floor((daynum+day-1)/7);
	}
	return weeknum;
};
	
// return number of days since start of year
Date.prototype.getYearDay = function () {
  var today = new Date(this);
  today.setHours(0); today.setMinutes(0); today.setSeconds(0);
  var tempDate = new Date(today);
  // set start of year
  tempDate.setDate(1);
  tempDate.setMonth(0);
  return Math.round(
  (today.getTime() - tempDate.getTime())
  / 86400 / 1000) + 1; // Jan/1 is day 1
};

// add format() to Date
Date.prototype.format = function(formatString) {
  var out = new String();
  var token = "";
  for (var i = 0; i < formatString.length; i++) {
    if (formatString.charAt(i) == token.charAt(0)) {
      token = token.concat(formatString.charAt(i));
      continue;
    }
    out = out.concat(this.convertToken(token));
    token = formatString.charAt(i);
  }
  return out + this.convertToken(token);
};

// internal call to map tokens to the date data
Date.prototype.convertToken = function (str) {
  switch(str.charAt(0)) {
    case 'y': // set year
      if (str.length > 2)
      return this.getFullYear();
      return this.getFullYear().toString().substring(2);
    case 'd': // set date
      return Date.zeroPad(this.getDate(),str.length);
    case 'D': // set day in year
      return this.getYearDay();
    case 'a':
      return this.getHours() > 11 ? "PM" : "AM";
    case 'H': // set hours
      return Date.zeroPad(this.getHours(),str.length);
    case 'h':
      return Date.zeroPad(this.get12Hours(),str.length);
    case 'm': // set minutes
      return Date.zeroPad(this.getMinutes(),2);
    case 's': // set secondes
      return Date.zeroPad(this.getSeconds(),2);
    case 'S': // set milisecondes
      return Date.zeroPad(this.getMilliseconds(),str.length);
    case 'x': // set epoch time
      return this.getTime();
    case 'Z': // set time zone
      return (this.getTimezoneOffset() / 60) + ":" +
      Date.zeroPad(this.getTimezoneOffset() % 60,2);
    case 'M': // set month
      if (str.length > 3) return this.getFullMonthName();
      if (str.length > 2) return this.getShortMonthName();
      return Date.zeroPad(this.getMonth()+1,str.length);
    case 'E': // set dow
      if (str.length > 3) return this.getDOWName();
      if (str.length > 1) return this.getShortDOWName();
      return this.getDay();
      default:
      return str;
  }
};

// Retreive the month's name in english
Date.prototype.getFullMonthName = function() {
  return Date.MONTH_NAMES[this.getMonth()];
};

// Retreive the abberviated month name in english
Date.prototype.getShortMonthName = function() {
  return Date.MONTH_NAMES[this.getMonth()].substring(0,3);
};

// Retreive the week day name in english
Date.prototype.getDOWName = function () {
  return Date.WEEKDAY_NAMES[this.getDay()];
};

// Retreive the abberviated week day name in english
Date.prototype.getShortDOWName = function () {
  return Date.WEEKDAY_NAMES[this.getDay()].substring(0,3);
};

// Retreive the hour in a 12 hour clock (without the AM/PM specification)
Date.prototype.get12Hours = function () {
  return this.getHours() == 0 ? 12 :
  (this.getHours() > 12 ? this.getHours() - 12 : this.getHours());
};

Date.frommysql = function(timestamp) {
	//function parses mysql datetime string and returns javascript Date object
	//input has to be in this format: 2007-06-05 15:26:02
	var regex=/^([0-9]{2,4})-([0-1][0-9])-([0-3][0-9]) (?:([0-2][0-9]):([0-5][0-9]):([0-5][0-9]))?$/;
	var parts=timestamp.replace(regex,"$1 $2 $3 $4 $5 $6").split(' ');
	return new Date(parts[0],parts[1]-1,parts[2],parts[3],parts[4],parts[5]);
};

// helper function to add required zero characters to fixed length fields
Date.zeroPad = function(num, width) {
  num = num.toString();
  while (num.length < width)
  num = "0" + num;
  return num;
};

if (typeof console == 'undefined') {
	var console = {
		info: function() {},
		dir: function() {},
		group: function() {},
		groupEnd: function() {}
	};
};

jQuery.fn.sort = function() {  
    return this.pushStack( [].sort.apply( this, arguments ), []);  
}; 

String.prototype.bool = function() {
    return (/^true$/i).test(this);
};

String.prototype.endsWith = function(str) {return (this.match(str+"$")==str); };
String.prototype.startsWith = function(str) {return (this.match("^"+str)==str); };

String.prototype.format = function() {
    var s = this;
    if ((s == null) || (s == 'undefined')) return s;
    if (arguments==null) return s;
    var i = arguments.length;
    if (i>0) {
    		while (i--) {
    			s = s.replace(new RegExp('\\{' + i + '\\}', 'gm'), arguments[i]);
    		}
    }
    return s;
};

if(!Array.indexOf){
    Array.prototype.indexOf = function(obj){
        for(var i=0; i<this.length; i++){
            if(this[i]==obj){
                return i;
            }
        }
        return -1;
    };
};

Array.prototype.find = function(searchStr) {
  var returnArray = false;
  for (var i=0; i<this.length; i++) {
    if (typeof(searchStr) == 'function') {
      if (searchStr.test(this[i])) {
        if (!returnArray) { returnArray = []; }
        returnArray.push(i);
      }
    } else {
      if (this[i]===searchStr) {
        if (!returnArray) { returnArray = []; }
        returnArray.push(i);
      }
    }
  }
  return returnArray;
};

String.prototype.formatArray = function(args) {
    var s = this;
    if ((s == null) || (s == 'undefined')) return s;
    if (args==null) return s;
    var i = args.length;
    if (i>0) {
    		while (i--) {
    			s = s.replace(new RegExp('\\{' + i + '\\}', 'gm'), args[i]);
    		}
    }
    return s;
};

$.extend({
	URLEncode:function(c) {
		var o='';
		var x=0;
		c=c.toString();
		var r=/(^[a-zA-Z0-9_.]*)/;
		while(x<c.length){
			var m=r.exec(c.substr(x));
			if(m!=null&&m.length>1&&m[1]!=''){
				o+=m[1];
				x+=m[1].length;
			}else{
				if(c[x]==' ')o+='+';
				else{
					var d=c.charCodeAt(x);
					var h=d.toString(16);
					o+='%'+(h.length<2?'0':'')+h.toUpperCase();
				}
				x++;
			}
		}
		return o;
	}, 
	URLDecode: function(s) {
		var o=s;var binVal,t; 
		var r=/(%[^%]{2})/;
		while((m=r.exec(o))!=null&&m.length>1&&m[1]!=''){
			b=parseInt(m[1].substr(1),16);
			t=String.fromCharCode(b);
			o=o.replace(m[1],t);
		}
		return o; 
	}
});

App = {};

App.Core = {
	
	isIOS : false,
	root : null,
	
	__preinit : function() {
		var ua = navigator.userAgent;		
		App.Core.isIOS = (ua.match(/iPhone/i) || ua.match(/iPod/i) || ua.match(/iPad/i));		
		var info = window.location;
		App.Core.root = info.protocol + '//' + info.host;		
	},
	
	redirect : function(type, link) {
		switch(type) {
			case 'direct':
				window.location = link;
			break;
			
			case 'timeout':
				setTimeout(function(){ window.location = link; return true; }, '3000');
			break;
			
			case 'internal_timeout':{
				setTimeout(function(){ App.Core.Nav.changeMenu(link, true); return true; }, '3000');
				break;
			}
			
			case 'internal':{
				App.Core.Nav.changeMenu(link, true);
				break;
			}
			
			default:
				return;
			break;
		}		
	}
		
};

App.Core.Service = {
	gateway : '/gateway/process/'
};

App.Core.Nav = {
	
	hasInit : false,
	selectedmenu : '/',
	hashHistory : new Array(),
	seoAbort : false,
	
	__preinit : function() {

		if (this.hasInit) return;
		this.hasInit = true;

		$('.hider').live('click', function(oEvent) { App.Core.Nav.switchHider(oEvent); });
		$('.menuitem').live('click', function(oEvent) { App.Core.Nav.mainMenu(oEvent); });
		$('.pagenav').live('click', function(oEvent) { App.Core.Nav.mainMenu(oEvent); return true; });
		$('.logout').live('click', function(oEvent) { App.Core.Nav.logout(oEvent); });

		$('[data-seo]').live('click', function(oEvent) { App.Core.Nav.informSEO(oEvent); });
		
		var selectedItems = $('.menuitem.selected');
		
		if (selectedItems.length > 0) {
			for (var counter=0; counter < selectedItems.length; counter++) {
				var target = $(selectedItems[counter]);
				url = $(target).data('url');		
				if ((url == 'undefined') || (url == null) || (url == '')) url = null;				
				this.selectedmenu = url;				
			}
		}		

		$(window).resize(function() {
			$('body').find('.hider').each(function() { 

				var parent = $(this).parent();
				var container = $(parent).parent();
				var article = $(container).find('.hpl');

				var mode = $(parent).attr('data-mode');
				if ((mode=='undefined') || (mode==null)) mode='open';
				
				switch(mode)
				{
					case 'closed': {
						$(parent).css({'right':'-320px'});
						$(article).width($(container).width()+320+'px');				
						break;
					}
				}
				
			});			
			
			return true;
		});

		// SEO Handler.....
		// Innovative style ;)
		// Written by Samuel D. Colak - Pure Awesomenesssssss
		
		var hash = window.location.hash;
		setInterval(function(){			
			
			var newhash = window.location.hash;
			var lasthash = null;
			
			if ((newhash==null) || (newhash=='undefined')) newhash = '';

			if (newhash != hash) {

				var direction = 'forward';
				
				if (App.Core.Nav.hashHistory.length > 0) {
					lasthash = (App.Core.Nav.hashHistory.length > 1) ? App.Core.Nav.hashHistory[App.Core.Nav.hashHistory.length-2] : App.Core.Nav.hashHistory[App.Core.Nav.hashHistory.length-1];		
					direction = ((lasthash==newhash) && (newhash.substring(1) != App.Core.Nav.selectedmenu)) ? 'backward' : 'forward';						
				}				
				
				if (direction=='forward') {
					App.Core.Nav.hashHistory.push(newhash);
				} else {
					if (App.Core.Nav.hashHistory.length > 0) App.Core.Nav.hashHistory.pop();
					$('*').triggerHandler('seo-back', {'url':newhash});
				}

				if (newhash.substring(1) != App.Core.Nav.selectedmenu) {
					$('.menuitem.selected,.top.selected').removeClass('selected');	
					if (!App.Core.Nav.seoAbort) {
						App.Core.Nav.changeMenu(newhash.substring(1), false);
					}
					$('*').triggerHandler('seo-forward', {'url':newhash});
				}
				
				App.Core.Nav.seoAbort = false;
				
				hash = newhash;
		    		
		    } else {
		    		if (App.Core.Nav.hashHistory.length == 0) {
		    			App.Core.Nav.hashHistory.push(newhash);
					App.Core.Nav.changeMenu(newhash.substring(1), false);
					$('*').triggerHandler('seo-start', {'url':newhash});
		    		}
		    }
		}, 100);
		
	},
	
	informSEO : function(oEvent) {
		
		var target = $(oEvent.currentTarget);
		if ((target == null) || (target == 'undefined')) return;
		
		var seoAttr = $(target).attr('data-seo');
		if ((seoAttr == null) || (seoAttr == 'undefined')) return;
		
		var seoUrl = App.Core.Nav.createSEOUrl(seoAttr);
		if (seoUrl.accept) { 		
			App.Core.Nav.seoAbort = true;
			window.location.hash = seoUrl.hash;
		}		
		
	},
	
	switchHider : function(oEvent) {		
		
		if (oEvent==null) return;
		
		var parent = $(oEvent.currentTarget).parent();
		var container = $(parent).parent();
		var article = $(container).find('.hpl');
		
		var mode = $(parent).attr('data-mode');
		if ((mode=='undefined') || (mode==null)) mode='open';
		
		switch(mode)
		{
			case 'open': {
				$(parent).css({'right':'-320px'});
				$(article).width($(container).width()+320+'px');				
				break;
			}
			case 'closed': {
				$(parent).css({'right':'0px'});
				$(article).width('100%');				
				break;
			}
		}		
		$(parent).attr('data-mode', ((mode=='open')?'closed':'open'));		
	},
	
	triggerRefresh : function() {
	
		var oData = { 'event': 'manual' };
		$('*').triggerHandler('page-refresh', oData);
	
	},
	
	mainMenu : function(oEvent) {
		
		if (oEvent == null) return;

		var url = (oEvent.currentTarget != null) ? $(oEvent.currentTarget).attr('data-url') : oEvent.data_url;
				
		var useEvent = {'type':oEvent.type, 'actualTarget':$(oEvent.currentTarget) };
		
		if (oEvent.currentTarget != null) {			
			
			if ($(oEvent.currentTarget).hasClass('disabled')) return;
			
			if (!$(oEvent.currentTarget).hasClass('menuitem')) {			
				useEvent.currentTarget = $('.menuitem[data-url="'+url+'"]');
			} else {
				useEvent.currentTarget = $(oEvent.currentTarget);
			}
		
		} else {
			
			useEvent = {'type':oEvent.type, 'actualTarget':oEvent, 'currentTarget': $('.menuitem[data-url="'+url+'"]') };
						
		}
		
		this.__changeMenu(encodeURI(url), useEvent, false);

	},

	createSEOUrl : function(url) {		
		if (url[0]=='#') return {'url':url, 'accept':false};
		if (url[1]=='$') url = url.substring(1);
		var header = document.location;
		var siteurl = header.protocol + '//' + header.host;		
		var urlout = siteurl + '#' + url;
		var cleanurl = url;
		if (cleanurl.indexOf('?')>0) {
			cleanurl = cleanurl.substring(0,cleanurl.indexOf('?'));
		}
		if (!url.startsWith('http')) {
			return {'url':urlout, 'accept':true, 'hash':'#'+url, 'clean':cleanurl };			
		}
		return {'url':url, 'accept':false, 'clean':cleanurl };
	},
	
	changeMenu : function(url, force) { 		
		if ((force=='undefined') || (force==null)) force=false;		
		if (url=='#') url = this.selectedmenu;
		this.__changeMenu(url, null, force);		
	},
	
	__changeMenu : function(url, oEvent, force) {
		
		var oTabData = null;
		if (oEvent && (($(oEvent.actualTarget).attr('data-detail') != null) || (oEvent.actualTarget.data_detail != null))) {
			var oData = null;
			if ($(oEvent.actualTarget).attr('data-detail') != null) { 
				oData = $(oEvent.actualTarget).attr('data-detail'); 
			} else {
				oData = oEvent.actualTarget.data_detail; 				
			}
			oTabData = App.UI._attrObject(oData);
			$('*').triggerHandler('event-track', {'category': oTabData.category, 'event':'view', 'info':oTabData.id});
		}
		
		var seoUrl = App.Core.Nav.createSEOUrl(url);
		if (seoUrl.accept) {
			window.location.hash = seoUrl.hash;
		}
		
		if (url[0]=='$') {
			
			var target = null;
			url = url.substring(1);

			if (oEvent != null) {
				target = $(oEvent.currentTarget).attr('data-target');
				if ((target == null) || (target=='undefined')) target = null;
				if (target != null) {
					window.open(url);
				} else {
					window.location = url;					
				}
			} else {
				window.location = url;
			}	
			
		} else if (url[0]=='#') {	
			
			var oData = { 'url': url.substring(1), 'object': $(oEvent.actualTarget) };
			$('*').triggerHandler('do-dialog', oData);				
			
		} else {
			
			if ((url != this.selectedmenu) || force) {
				
				$('#mainbody').load(url, function() {
					var oData = { 'from_url': this.selectedmenu, 'to_url': url, 'event': 'auto' };
					$('*').triggerHandler('page-changed', oData);
					$('*').triggerHandler('page-refresh', oData);
					if(oTabData != null) $('*').triggerHandler('create-tab', oTabData);																				
				});
														
				this.selectedmenu = url;
																
				if ((oEvent != null) && ($(oEvent.currentTarget).hasClass('menuitem'))) {
					
					var parent = ($(oEvent.currentTarget).hasClass('top')) ?
						$(oEvent.currentTarget) : $(oEvent.currentTarget).parents('.top');
					
					if ($(parent).hasClass('selected')) {
						$('.menuitem.selected', parent).removeClass('selected');
					} else {
						$('.menuitem.selected,.top.selected', $(parent).parent()).removeClass('selected');												
						$(parent).addClass('selected');		
					}					
					
					if ($(oEvent.currentTarget) === $(parent)) return;
					$(oEvent.currentTarget).addClass('selected');
					
				} else {
					
					var menuitems = $('.menuitem');
					if (menuitems.length > 0) {
						var counter = 0;
						do {
							if ($(menuitems[counter]).attr('data-url')==seoUrl.clean) {
								$(menuitems[counter]).addClass('selected');
								if (!$(menuitems[counter]).hasClass('top')) {
									$('.top.selected').removeClass('selected').find('.menuitem.selected').removeClass('selected');		
									$(menuitems[counter]).parents('.top').addClass('selected');
								}
								break;
							}
						} while (++counter < menuitems.length);						
					}
					
				}
				
			}
			
		}			
		
	}
		
};

App.Core.Localize = {
	
	dictionary : new Hashtable(),
	lang : 'en',
	loaded : false,
	
	__preinit : function() {
		
	},

	load : function(lang) {
		if ((lang=='undefined') || (lang==null)) return;
		
	}
		
};

App.Core.Loader = {
		
	hasInit : false,	
	status : 0,
	
	__preinit : function() {
		if (this.hasInit) return;
		this.hasInit = true;
		// do pre-init here...
	},
	
	scan : function() {				
		$('.loadme').each(function() {
			App.Core.Loader.__loadme(this);
		});		
	},
	
	__loadme : function(target) {
		if (target == null) return;
		if ($(target).attr('data-url') != null) {
			$(target).load($(target).attr('data-url'), function() {				
				$(target).removeClass('loadme');				
			});
			$(target).removeAttr('data-url');
		}
	}	

};

App.Core.Security = {

	isLoggedIn : false,
	checking : false,
	timeron : false,
	hasInit : false,
	refreshcount : 0,
	code : '12345',
	messageTop : -1,
	
	init : function() {
		if (App.Core.Security.hasInit) return;
		App.Core.Security.hasInit = true;
		$('*').bind('page-refresh page-changed', function(object, data) { App.Core.Security.refreshcount = 0; });		
		App.Core.Security.checkLoginState();
	},
	
	checkLoginState : function() {
		if (this.checking) return;
		this.checking = true;
		var oData = {};
		$.ajax({
				type: "get",
				dataType: "json",
				error: function(data) {
					App.Core.Security.recoverFailed(data);
				},
				success: function(data) {
					App.Core.Security.processMessages(data);
					App.Core.Security.processJsonData(data);
				},				
				url:'/ds/security/isloggedin/'+App.Core.Security.messageTop, 
				data:oData
			});		
	},
	
	checkloginStatus : function() {
		// trigger logout functionality at backend...
		var oData = {};
		var oRequest = {actions: [{action:'checkloginStatus',data:oData }],jw: App.Core.Security.code};
		App.Core.Application.appHandler(oEvent, oRequest);		
	},
	
	recoverFailed : function() {
		this.checking = false;
	},

	processMessages : function(content) {
	
		if ((content==null) || (content.messages==null)) return;
		
		var newtop = parseInt(content.messages.top);
		if (newtop == App.Core.Security.messageTop) return; // no new messages !!
		App.Core.Security.messageTop = newtop; // set this fast to prevent timeout issues....

		var messages = content.messages.set;
		if ((messages==null) || (messages.length==0)) return;
		for (var counter=0; counter<messages.length; counter++) {
			var oData = { 'message': messages[counter] };
			$('*').triggerHandler('do-notify', oData);			
		}
				
	},
	
	processJsonData : function(content) {
		
		if (content.loggedin=='0') { // logged out!
			if (this.isLoggedIn) {
				this.isLoggedIn = false;
				App.Core.redirect('direct', '/');
			} else {
				this.timeron = false;
				this.isLoggedIn = false;
			}
		} else {
			this.isLoggedIn = true;
			if (!this.timeron) {
				this.timeron = true;
				$.doTimeout(30000, function() { // 30 seconds
					App.Core.Security.checkLoginState();
					App.Core.Security.refreshcount ++;
					if (App.Core.Security.refreshcount > 10) {
						App.Core.Nav.triggerRefresh();												
					}
					return App.Core.Security.timeron;
				});	
			}				
		}
		
		this.checking = false;
		
	}
	
};

App.Core.Application = {
	
	hasInit : false,
	msgBox : $('#response .msg'),
	status : false,
	
	__preinit : function(){
		
		if (this.hasInit) return;
		this.hasInit = true;
		
		$('*').bind('do-submit', function(object, data){ App.Core.Application.__submit(data); });
		$('*').bind('do-ajaxsubmit', function(object, data){ App.Core.Application.__ajaxSubmit(data); });
		$('*').bind('do-formdata', function(object, data){ return App.Core.Application.__retrieveFormData(data); });
		$('*').bind('handle-app', function(object, data){ App.Core.Application.__appHandler(data); });
		$('*').bind('handle-status', function(object, data){ App.Core.Application.__handleStatus(data); });
		
		$('[data-event]').live('click', function(oEvent){ App.Core.Application.__handleEvent(oEvent, 'event'); });
		$('[data-workflow]').live('dblclick', function(oEvent){ App.Core.Application.__handleEvent(oEvent, 'workflow'); });		
//		$('[data-retrieve]').live('click', function(){ var el = $(this).data('retrieve'); $('*').triggerHandler('do-submit', { 'target':el, 'action':'myDetails' }); });
	},
	
	__handleEvent : function(oEvent, type) {
		var oElement = oEvent.currentTarget;
		var attr;
		
		if(type == 'event') attr = $(oElement).attr('data-event');
		else attr = $(oElement).attr('data-workflow');
		
		for(_oArgs in eval('('+ attr +')')) {
			if(typeof _oArgs != 'function') var oArgs = eval('('+ attr +')');
			else console.info('No Functions allowed');
		}
		
		if(typeof oArgs != 'object') return;
			
		if (oArgs.actions != null || oArgs.actions != undefined) {
			if (typeof App.Core[oArgs.actions][oArgs.event] == 'function') {
				App.Core[oArgs.actions][oArgs.event](oElement, oArgs.args);
			}  else {
				console.info('Function ' + [oArgs.actions][oArgs.event] + ' not found in Core!');
			}
		}
		
		if (oArgs.action != null || oArgs.action != undefined) {
			if (typeof App[oArgs.action][oArgs.event] == 'function') {
				App[oArgs.action][oArgs.event](oElement, oArgs.args);
			} else {
				console.info('Function ' + [oArgs.action][oArgs.event] + ' not found!');
			}
		}
							
		if (oArgs.tiny != null || oArgs.tiny != undefined) {
			if (typeof App.UI.Tiny[oArgs.event] == 'function') {
				App.UI.Tiny[oEvent.event](oElement, oArgs.args);
			} else {
				console.info('Function UI.Tiny.' + [oArgs.event] + ' not found!');
			}
		}
		
	},
	
	__retrieveFormData: function(data) {
		var oFormData		= {};
		var aInputs 		= $('#' + data.target + ' input, #' +  data.target + ' select, #' +  data.target + ' textarea');
		var oInput			= {};
		var sInputName		= '';
		var sInputValue		= '';
		var sDefaultValue	= '';
		var sInputTag		= '';
		
		for (var i = 0; i < aInputs.length; i++) {
			
			oInput			= aInputs[i];
			sInputTag		= oInput.nodeName;
			sInputType		= oInput.getAttribute('type');
			sInputName		= oInput.getAttribute('name');
			sInputValue		= oInput.value;
			sInputClass		= oInput.getAttribute('class');
			sDefaultValue	= oInput.getAttribute('data-default');
						
			switch (sInputTag.toLowerCase()) {
					
				case "input": {
					
					if (sInputType == 'checkbox') {
						sInputValue = ((oInput.checked) ? 1 : 0);
					}
					
					if (sInputType == 'radio') {
						var aRadio = document.getElementsByName(sInputName);
						for (var r=0; r < aRadio.length; r++) {
							if (aRadio[r].checked) sInputValue = aRadio[r].value;
						}
					}
					
					if(oInput.tagName.toLowerCase() == 'textarea') {
						sInputValue = ((sInputClass == 'tinymce') ? tinyMCE.activeEditor.getContent() : oInput.value);
					}
					
					if (typeof oFormData[sInputName] == 'string' && sInputType != 'radio') {
						var sOldValue	= oFormData[sInputName];
						oFormData[sInputName] = [];
						oFormData[sInputName][oFormData[sInputName].length] = sOldValue;
						oFormData[sInputName][oFormData[sInputName].length]	= sInputValue;
					} else if (typeof oFormData[sInputName] == 'object') {
						oFormData[sInputName][oFormData[sInputName].length]	= sInputValue;
					} else {
						oFormData[sInputName]	= sInputValue;
					}					
					
					break;
				}
					
				case "select": {					
					oFormData[sInputName] = sInputValue;
					break;
				}
				
				default: {
					
					console.info("unknown tagtype - " + sInputTag.toLowerCase());
					break;
				}
					
			}

		}
		
		return oFormData;
	},
	
	__appHandler : function(oRequest){
			
		var msgBox = $('#response .msg');
		
		var handleResponse = function(oData) {
			
			if(oData != null){
				
				if (oData.status == false) {
					
					var status = false;
					App.Core.Application.__createMsg(status, oData);
					
					if ((typeof oData.link != null) && (typeof oData.link != 'undefined')) App.Core.redirect('internal_timeout', oData.link);
					setTimeout(function(){ App.Core.Application.__clearMsg(); return true; }, '3000');
					
				} else {
					
					var status = true;
					
					if(typeof oData.action != 'undefined') {
						
						var oArgs = (oData.args != null) ? oData.args : {};
						App[oData.action][oData.event](oArgs);
						
					} else {
						
						if ((oData.mode == null) || oData.mode == 'undefined'){
							
							App.Core.Application.__createMsg(status, oData);
							if ((oData.link != null) && (oData.link != 'undefined')) App.Core.redirect('timeout', oData.link);
							if((oData.message != null) || (oData.message != 'undefined')) setTimeout(function(){App.Core.Application.__clearMsg(); return true; }, '3000');
														
						} else {
							$('*').triggerHandler('handle-status', oData);							
						} 
						
					}
				}
				
			} else {
				console.info('No data received');
			}
		};

		$.post(App.Core.Service.gateway, {request: $.toJSON(oRequest)}, handleResponse, 'json');
		
	},
	
	__handleStatus : function(oData){
		var msgBox = $('#response .msg');
		var hasClosed = false;
		
		if((oData.message != null) || (oData.message != 'undefined')) {
			var status = true;
			App.Core.Application.__createMsg(status, oData);
		}
		
		switch(oData.mode){
						
			case 'redirect':{ // Redirect
				App.Core.redirect('internal', oData.link);
				if(oData.dialog == true) App.UI.DialogManager.close();
				break;
			}
			
			case 'hard-redirect':{ // Refresh
				App.Core.redirect('direct', oData.link);				
				break;
			}
			
			case 'refresh':{ // Refresh
				$('*').triggerHandler('page-refresh', null);
				if(oData.dialog == true) App.UI.DialogManager.close();	
				break;
			}
			
			case 'refresh-data':{
				$('*').triggerHandler('data-refresh', null); // redraws data
				break;
			}
			
			case 'dialog':{
				App.UI.DialogManager.close();
				break;
			}
			
			case 'dialog-refresh':{
				$('*').triggerHandler('page-refresh', null);
				App.UI.DialogManager.close();
				break;
			}
			
			case 'dialog-redirect':{ // Redirect
				App.Core.redirect('internal', oData.link);
				App.UI.DialogManager.close();
				break;
			}
			
			case 'dialog-redirect-hard':{ // Refresh
				App.Core.redirect('direct', oData.link);
				App.UI.DialogManager.close();			
				break;
			}
						
			case 'thx':{
				if(oData.target != null){
					if(oData.target == 'confirmation'){
						$('#'+ oData.target).slideUp('50', function(){ $('#'+ oData.target).remove(); });
					}
				}				
				break;
			}
						
			default:	
				break;
			
		}
		
		if(!hasClosed) setTimeout(function(){ App.Core.Application.__clearMsg(); }, '3000');
				
	},
	
	__createMsg : function(status, oData){
		
		var msgBox = this.msgBox;
		var status = (status) ? 'true' : 'false';
		
		var msg = '<div class="msg '+ status +'">'+ oData.message +'</div>';
		
		if($(msgBox).is(':visible')){
			$('#response').prepend(msg).slideUp('50', function(){ $('#response .msg').fadeIn('50'); });
		} else {
			$('#response').append(msg).slideDown('50', function(){ $('#response .msg').fadeIn('50'); });
		}
		
	},
	
	__clearMsg : function(){
		var parent = $('#response');
		$(parent).slideUp('50');
		$('.msg', parent).fadeOut('50', function(){ $('.msg', parent).remove(); });
		
	},
	
	__submit: function(data) {
		
		if(data.target != null) var oFormData = this.__retrieveFormData(data);
		else console.info('Target is not set');
		
		if ((data['action'] != null) || (data['action'] != 'undefined')) var oRequest = {actions:[{action:data.action,data:oFormData}],jw:App.Core.Security.code};
		else  console.info('No action available');

		this.__appHandler(oRequest);
	},
	
	__ajaxSubmit : function(data){
		
		var oForm = $('#'+ data.form);		
		var config = {
			target : App.Core.Application.msgBox,
			dataType : 	'json',
			success : function(oData){
				$('*').triggerHandler('handle-status', oData);
			}	
		};
		
		$(oForm).ajaxSubmit(config);
	}
	
};


App.Core.Notifier = {
	
	hasInit : false,
	total : 0,
	history : [],
	
	__preinit : function(){
		if (this.hasInit) return;
		this.hasInit = true;
		
		if (!App.Core.isIOS) {
			$('#notifier').css({'display':'inline-block'});
		}
		
		$('*').bind('do-notify', function(object, data){ App.Core.Notifier.__processMessages(data); });
		$('#notify .icon.history, #archive h5').live('click', function(oEvent){ App.Core.Notifier.__toggleHistory(); });
	},
	
	__processMessages : function(data){
		
		var type = data.message.id_messagetype;
		
		var oHtml = '';
		oHtml += '<li id="msg_'+ data.message.id +'" class="'+ type +'">';
		oHtml += data.message.content;
		oHtml += '</li>';
		
		App.Core.Notifier.total += 1;
		if(App.Core.Notifier.total == 1) this.__setTimer('msg');
		
		this.__updateComponent(oHtml, 'msg');
		
	},
		
	__updateComponent : function(oHtml, mode){
			
		if(mode == 'msg') this.__updateTotal(mode);
		
		if($('#'+ mode +' li').length == 0) {
			var wrapper = $('<ul id="'+ mode +'"></ul>');
			$(wrapper).html(oHtml);
			
			if(mode == 'msg') $('#notify').append(wrapper);
			if(mode == 'history') $('#archive').append(wrapper);
			
		} else {
			$('#'+ mode).prepend(oHtml);
		}
		
		if(mode == 'msg') $('#notify header h5').addClass('active');
		
		
	},
	
	__updateTotal : function(mode){
		if(mode == 'msg') $('#notify header .counter').html('('+ App.Core.Notifier.total +')');
		if (mode == 'history') $('#archive header .counter').html('(' + App.Core.Notifier.history.length + ')');
	},
	
	__setTimer : function(mode){				
				
		$.doTimeout(30000, function(){
			var el = $('#msg li:last');
			var hist = $(el).clone();
			$(el).remove();
			App.Core.Notifier.history.push(hist);
			App.Core.Notifier.total += -1;
			App.Core.Notifier.__updateTotal(mode);
			App.Core.Notifier.__checkHistory();
			var finish = (App.Core.Notifier.total > 0);
			
			if(!finish) {
				$('#notify header h5').removeClass('active');
				$('#msg').remove();
			}			
			
			return finish;
		});
		
	},
	
	__checkHistory : function(){
		var history = this.history;
		var total = history.length;
		var hIcon = $('#notify .icon.history');
		
		if(total > 0){
			$('.counter', hIcon).html('('+ total +')');
			if(!$(hIcon).is(':visible')) $(hIcon).fadeIn('50');
			this.__updateTotal('history');
			this.__createHistory();
		} else {
			 $(hIcon).hide();
		}
		
	},
	
	__toggleHistory : function(){
		if($('#archive').is(':visible')) $('#archive').slideUp('50');
		
		if(!$('#archive').is(':visible')) $('#archive').slideDown('50');
	},
	
	__createHistory : function(){
		
		var aHistory = this.history;
		
		if ($('#history li').length > 0)  $('#history').remove();
		
		for(var h=0; h < aHistory.length; h++){		
			this.__updateComponent(aHistory[h], 'history');
		}
		
	}
	
};

App.Track = {
	
	hasInit : false,
	
	__preinit : function(){
		
		if (this.hasInit) return;
		this.hasInit = true;

		$('*').bind('page-refresh', function(object, data) { App.Track.pageChanged(data); });		
		$('*').bind('event-track', function(object, data) { App.Track.event(data); return true; });
		
	},
	
	event : function(data) {		
		if ((data != null) && (_gaq != 'undefined') && (_gaq != null)) {
			_gaq.push(['_trackEvent', data.category, data.event, data.info]);			
		}		
	},
	
	pageChanged : function(data) {		
		if ((data != null) && (_gaq != 'undefined') && (_gaq != null)) {
			if (data.to_url != null) {
				_gaq.push(['_trackEvent', 'pages', 'pagechanged', data.to_url]);
			}		
		}		
	}
				
};

$(document).ready(function() {	

	$('body').disableSelection();

	App.Core.__preinit();
	
	App.Core.Loader.__preinit();
	App.Core.Loader.scan();
	App.Core.Localize.__preinit();	
	
	App.Core.Security.init();
	App.Core.Nav.__preinit();
	App.Core.Application.__preinit();
	App.Core.Notifier.__preinit();
	
	App.Track.__preinit();
	
});

