// JavaScript Document
/*
	Author: Willy
	Modified: 2008/11/28
*/
if (!window.tagala) var tagala = {};
if (!tagala.Debug) tagala.Debug = {};

Object.extend(tagala,
{
	packs:['locale', 'template'],
	onload:null,
	_handlers:[]
});

tagala.Dispatchable = 
{
	_each:function (iterator)
	{
		this._handlers._each(iterator);
	},

	register:function (handler)
	{
		var msg = '';
		if (!this.include(handler)) this._handlers.push(handler);
	},

	unregister:function (handler)
	{
		this.handlers = this._handlers.without(handler);
	},

	dispatch:function (callback)
	{
		var args = $A(arguments);
		args.shift();
		this.each(function(handler)
		{
			try
			{
				(handler[callback] || Prototype.emptyFunction).apply(this, args);
			}
			catch (e)
			{
 				(tagala.Debug.confirm || Prototype.emptyFunction)('Dispatch error with ' + callback + '(' + e.message + ') at ' + (tagala.Debug.dumpProperty || Prototype.emptyFunction)(e));
			}
		}, this);
	}
};
Object.extend(tagala.Dispatchable, Enumerable);
Object.extend(tagala, tagala.Dispatchable);

tagala.DispatchHandler = Class.create(tagala.Dispatchable,
{
	initialize:function ()
	{
		this._handlers = [];
	}
});

// All static files are loaded
$(document).observe('dom:loaded', function ()
{
	if (!document.body) return;
	var session = new tagala.Session();
	session.register(
	{
		onEnd:function ()
		{
			tagala.dispatch('onLoaded');
			(tagala.onload || Prototype.emptyFunction)();
		}
	});

	// Initialize the tagala packs objects.
	tagala.packs.each(function (pack)
	{
		if (tagala[pack = pack.sub(/^tagala-/, '').capitalize()]) tagala[pack.toLowerCase()] = new tagala[pack](session);
	});

	// Loading necessary resource files dynamicly 
	session.begin();
	tagala.dispatch('onCreate');
	session.commit();
});

tagala.Common = Class.create(
{
	initialize:function ()
	{
	},

	showWait:function ()
	{
		var waitImg = $('waitImg') ||
									$(document.body).appendTag('IMG',
									{
										id:'waitImg',
										src:tagala.config.waitImgSrc
									}).setStyle(
									{
										zIndex:100010,
										position:Prototype.Browser.IE ? 'absolute' : 'fixed'
									});
		var docDm = document.viewport.getDimensions();
		var imgDm = waitImg.getDimensions();
		waitImg.setStyle(
		{
			top:((docDm.height - imgDm.height) / 2).floor() + 'px',
			left:((docDm.width - imgDm.width) / 2).floor() + 'px'
		}).show();
	},

	hideWait:function ()
	{
		$('waitImg').hide();
	},

	getCookies:function ()
	{
		return document.cookie.split(';').inject({}, function(hash, pair)
		{
	    if ((pair = pair.split('='))[0])
			{
	      var key = decodeURIComponent(pair.shift()).strip();
	      var value = pair.length > 1 ? pair.join('=') : pair[0];
	      if (value != undefined) value = decodeURIComponent(value);
	
	      if (key in hash)
				{
	        if (!Object.isArray(hash[key])) hash[key] = [hash[key]];
	        hash[key].push(value);
	      }
	      else hash[key] = value;
	    }
	    return hash;
  	});
	},

	getCookie:function (name)
	{
		return this.getCookies()[name];
	},

	setCookie:function (name, value, attributes)
	{
		attributes = attributes || {};
		if (Object.isString(name))
			document.cookie = name + '=' + escape(value) +
			(isFinite(attributes.days) ? ';expires=' + new Date(new Date().getTime() + attributes.days * 24 * 60 * 60 * 1000).toGMTString() : '') +
			(Object.isString(attributes.path) ? ';path=' + attributes.path : '') +
			(Object.isString(attributes.domain) ? ';domain=' + attributes.domain : '') +
			(attributes.secure ? ';secure' : '');
	},

	deleteCookie:function (name, attributes)
	{
		attributes = attributes || {};
		if (tagala.common.getCookie(name))
			document.cookie = name + '=' +
			(Object.isString(attributes.path) ? ';path=' + attributes.path : '') +
			(Object.isString(attributes.domain) ? ';domain=' + attributes.domain : '') +
			';expires=Thu, 01-Jan-1970 00:00:01 GMT';
	},

	loadScript:function (src, options)
	{
		options = options || {};
		if (options.session)
			new Ajax.Request(src, Object.extend(
			{
				method:'get',
				evalJSON:false
			}, options));
		else
			$$('HEAD')[0].appendTag('SCRIPT', {type:'text/javascript', src:src});
	},

	includeScript:function (src)
	{
		document.write('<' + 'script type="text/javascript" src="' + src + '"> ');
		document.write('</' + 'script' + '>');
	},

	loadJSON:function (src, options)
	{
		if (!Object.isString(src)) return;
		new Ajax.Request(src, Object.extend(
		{
			method:'get',
			evalJS:false,
			evalJSON:'force'
		}, options));
	},

	loadCSS:function (src, title)
	{
		if (!Object.isString(src)) return;
		$$('HEAD')[0].appendTag('LINK',
			{
				type:'text/css',
				media:'all',
				href:src,
				rel:(Object.isString(title) ? 'alternate ' : '' ) + 'stylesheet',
				title:title
			});
	},

	unloadCSS:function (title)
	{
		$$('LINK[rel="alternate stylesheet"][title^="' + title + '"]').invoke('remove');
	},

	setStylesheet:function (titles)
	{
		if (!Object.isArray(titles)) titles = [titles];
		$$('LINK[rel="alternate stylesheet"][title]').each(function(el)
		{
			el.disabled = true;
			if (titles.include(el.readAttribute('title'))) el.disabled = false;
		});
	}
});
tagala.common = new tagala.Common();

tagala.Location = Class.create({
	initialize:function (_location, params) {
		params = params || {};
		if (Object.isString(_location) && /^(?:(\w+:)?\/\/(([^\/\:]*)(?:\:(\d+))?))?([^?#]*)(\?[^#]*)?(#.*)?$/.test(_location)) {
			this.protocol = RegExp.$1 || location.protocol;
			this.host = RegExp.$2 || location.host;
			this.hostname = RegExp.$3 || location.hostname;
			this.port = RegExp.$4 || location.port;
			this.pathname = RegExp.$5;
			this.search = RegExp.$6;
			this.hash = RegExp.$7;
		}
		else if (_location) {
			this.protocol = _location.protocol;
			this.host = _location.host;
			this.hostname = _location.hostname;
			this.port = _location.port;
			this.pathname = _location.pathname;
			this.search = _location.search;
			this.hash = _location.hash;
		}
		this.addSearch(params.search);
		this.addHash(params.hash);
		this.href = this.__toUrl();
		if (this.hash) this.trimedHash = this.hash.toTrimedHash();
	},

	addSearch:function (param) {
		if (param == null) return;
		if (!Object.isString(param)) param = Object.toQueryString(param);
		this.search = (this.search ? this.search + '&' : '?') + param;
		this.href = this.__toUrl();
		return this;
	},

	addHash:function (param) {
		if (param == null) return;
		if (!Object.isString(param)) param = Object.toQueryString(param);
		this.hash = (this.hash ? this.hash + '&' : '#') + param;
		this.trimedHash = this.hash.toTrimedHash();
		this.href = this.__toUrl();
		return this;
	},

	__toUrl:function () {
		return this.protocol + '//' + this.host + this.pathname + this.search + this.hash;
	},

	toString:function () {
		return this.href;
	}
});

Object.extend(String.prototype,
{
	toPath:function ()
	{
		return ((this.blank() ? '.' : this.strip()) + '/').gsub('//', '/');
	},

	toStaticUrl:function ()
	{
		var url = this.unescapeHTML();
		return Object.isFunction(parent.buildStaticLink) ? parent.buildStaticLink(url) : tagala.config.site_url + 'index.php?mapY=24.666128&mapX=120.860939&zoom=12&dt=2008/4/23&dt_mode=CY&view=' + escape(url);

	},

	toLanguageId:function ()
	{
		return this.toLowerCase().gsub('-', '_');
	}
});

tagala.Element =
{
	appendTag:function (el, tagName, attributes)
	{
		if (tagName)
			tagName = tagName.toUpperCase();
		else
			return;
		if (tagName == 'A' && attributes && attributes.href && /^https?:\/\//.test(attributes.href)) attributes.href = attributes.href.toStaticUrl();
		return $(el).appendChild(new Element(tagName, attributes));
	},

/*
	Valid params:
		P1. {A:ATTR}
		P2. {T:TEXT}
		P3. {A:ATTR, T:TEXT}
		P4. {T:TEXT, A:ATTR}
	ATTR:
		A1. {attr:TEXT[, attr':TEXT']*}
	TEXT:
		T1. string
		T2. {K:T1[, V:{key:TEXT[, key':TEXT']*}]}
*/
	appendLocale:function (el, params, tagName, attributes)
	{
		(attributes = attributes || {})[tagala.config.localeId] = (params instanceof Object) ? Object.toJSON(params) : params;
		return $(el).appendTag(tagName || 'SPAN', attributes);
	},

	appendA:function (el, url, attributes)
	{
    el = $(el).appendTag('A', Object.extend(attributes || {}, {href:url}));
    if (tagala.view) el.observe('click', tagala.view.onClickAnchor);
		return el;
	},

	appendImg:function (el, src, alt, width, height, attributes)
	{
		(attributes = attributes || {}).src = src;
		if (width) attributes.width = width;
		if (height) attributes.height = height;
		return $(el).appendLocale({A:{alt:alt}}, 'IMG', attributes);
	},

	appendDiv:function (el, id, className, attributes)
	{
		attributes = attributes || {};
		if (id) attributes.id = id;
		el = $(el).appendTag('DIV', attributes);
		if (className) el.addClassName(className);
		return el;
	},

	toLocale:function (el, language)
	{
		var params;
		el = $(el);
		if (!(params = el.readAttribute(tagala.config.localeId))) return;
		if (params.isJSON()) params = params.evalJSON();
		if (params.A)
			$H(params.A).each(function(pair)
			{
				el.writeAttribute(pair.key, tagala.locale.tr(pair.value));
			});
		else if (!params.T)
			params = {T:params};
		if (params.T) el.update(tagala.locale.tr(params.T, language));
		return el;
	}
};
Element.addMethods(tagala.Element);

tagala.Locale = Class.create(tagala.DispatchHandler,
{
	language:navigator.userLanguage || navigator.language,

	initialize:function ($super)
	{
		$super();
	},

	setLanguage:function (language)
	{
		if (Object.isString(language)) this.language = language;
	},

	getLanguage:function ()
	{
		return this.language;
	},

	tr:function (params, language)
	{
		if (!params) throw new Exception();
		var retVal, key;
		if (!(key = params.K || params)) return '';
		var dM = tagala.template.getLocaleMessages(tagala.config.defaultTemplate);
		var tM = tagala.template.getLocaleMessages();
		language = (language || this.language).toLanguageId();
		if (!retVal && tM && tM[language]) retVal = tM[language][key];
		if (!retVal && tM && tM[tagala.config.defaultLanguage.toLanguageId()]) retVal = tM[tagala.config.defaultLanguage.toLanguageId()][key];
		if (!retVal && dM[language]) retVal = dM[language][key];
		if (!retVal && dM[tagala.config.defaultLanguage.toLanguageId()]) retVal = dM[tagala.config.defaultLanguage.toLanguageId()][key];
		retVal = retVal || key;
		if (params.V)
		{
			$H(params.V).each(function (pair)
			{
				if (pair.value instanceof Object) params.V[pair.key] = this.tr(pair.value, language);
			}, this);
			retVal = retVal.interpolate(params.V);
		}
		return retVal;
	},

	trPage:function (language)
	{
		$$('[' + tagala.config.localeId + ']').invoke('toLocale');
		this.dispatch('onComplete', {language:language});
	}
});

tagala.Template = Class.create(
{
	initialize:function (session)
	{
		this.loadedTemplates = [];
		this.tempaltes = {};
		this.baseFolder = (tagala.config.baseFolder || '').toPath();
		this.templatesBase = (Object.isString(tagala.config.templateFolder) ? tagala.config.templateFolder : (this.baseFolder + 'templates/')).toPath();
		tagala.register(
		{
			onCreate:function ()
			{
				this.loadTemplate({template:(this.currentTemplate = tagala.config.defaultTemplate), session:session}, true);
			}.bind(this)
		});
	},

	loadTemplate:function (options, setCurrent)
	{
		options = options || {};
		var template = options.template = options.template || tagala.config.defaultTemplate;
		if (!this.loadedTemplates.include(template))
		{
			this.loadedTemplates.push(template);
			this.tempaltes[template] = {};
			this.tempaltes[template].messages = {};
			tagala.common.loadCSS(this.getTemplateFolder(template) + 'css/template.css', template);
			if (tagala.View) this.loadHandler(options);
		}
		this.loadLocale(options);
		if (setCurrent)
			if (options.session)
				options.session.register(
				{
					onEnd:function ()
					{
						this.setTemplate(template);
					}.bind(this)
				});
			else
				this.setTemplate(template);
	},

	loadLocale:function (options)
	{
		var template, srcLanguage;
		if (!options || !Object.isString(template = options.template)) return;
		var srcPrefix = this.getTemplateFolder(template) + 'js/locale/locale_';
		var srcDefaultLanguage = srcPrefix + tagala.config.defaultLanguage.toLanguageId() + '.js';
		var language = (options.language || tagala.locale.getLanguage()).toLanguageId();
		if (language != tagala.config.defaultLanguage) srcLanguage = srcPrefix + language.toLanguageId() + '.js';

		if (!this.tempaltes[template].messages[language])
		{
			tagala.common.loadJSON(srcDefaultLanguage, 
			{
				onSuccess:function (response)
				{
					this.tempaltes[template].messages[tagala.config.defaultLanguage.toLanguageId()] = response.responseJSON;
				}.bind(this),
				session:options.session
			});
			if (srcLanguage) tagala.common.loadJSON(srcLanguage, 
			{
				onSuccess:function (response)
				{
					this.tempaltes[template].messages[language] = response.responseJSON;
				}.bind(this),
				session:options.session
			});
		}
	},

	loadHandler:function (options)
	{
		var template;
		if (!tagala.View || !options || !Object.isString(template = options.template) || this.tempaltes[template].handlers) return;

		delete tagala.Handler;
		tagala.common.loadScript(this.getTemplateFolder(options.template) + 'js/handlers.js',
		{
			onComplete: function(response)
			{
				if (response.request.success())
					if (tagala.Handler)
						this.tempaltes[template].handlers = new tagala.Handler();
					else
						(tagala.Debug.confirm || Prototype.emptyFunction)("Can't create #{template}'s Handlers instance.".interpolate({template:template}));
			}.bind(this),
			session:options.session
		});
	},

	releaseTemplate:function (template)
	{
		if (this.loadedTemplates.include(template))
		{
			try
			{
				delete this.tempaltes[template];
				this.loadedTemplates = this.loadedTemplates.without(template);
			}
			catch (e) {}
			tagala.common.unloadCSS(template);
		}
	},

	releaseLoadedTemplates:function ()
	{
		this.loadedTemplates.each(function (template)
		{
			if (template != tagala.config.defaultTemplate) this.releaseTemplate(template);
		}, this);
		this.setTemplate();
	},

	setTemplate:function (template)
	{
		if (template != tagala.config.defaultTemplate && this.loadedTemplates.include(template))
			this.currentTemplate = template;
		else
			this.currentTemplate = tagala.config.defaultTemplate;
		this.setStyle();
		tagala.locale.trPage();
	},

	setStyle:function (style)
	{
		this.style = style || this.style;
		var templates = [tagala.config.defaultTemplate];
		if (!templates.include(this.currentTemplate)) templates.push(this.currentTemplate);
		tagala.common.setStylesheet(templates.inject([], function (titles, template)
		{
			titles.push(template);
			titles.push(template + '_' + this.style);
			return titles;
		}, this));
	},

	getTemplate:function ()
	{
		return this.currentTemplate;
	},

	getLoadedTemplates:function ()
	{
		return this.loadedTemplates;
	},

	getTemplateFolder:function (template)
	{
		template = template || this.currentTemplate;
		return this.templatesBase + template + '/';
	},

	getLocaleMessages:function (template)
	{
		template = template || this.currentTemplate;
		if (template && this.tempaltes[template])
			return this.tempaltes[template].messages;
	},

	getHandlers:function (template)
	{
		template = template || this.currentTemplate;
		if (template && this.tempaltes[template])
			return this.tempaltes[template].handlers;
	}
});

tagala.Session = Class.create(tagala.DispatchHandler,
{
	initialize:function ($super)
	{
		$super();
		this.requestCount = 0;
		this.started = false;
	},

	begin:function ()
	{
		if (!this.started && this.requestCount > 0) this.dispatch('onStart');
		this.started = true;
	},

	commit:function ()
	{
		if (this.started && this.requestCount == 0) this.dispatch('onEnd');
		this.started = false;
	},

	add:function ()
	{
		if (++this.requestCount == 1)
		{
			tagala.common.showWait();
			if (this.started) this.dispatch('onStart');
		}
	},

	release:function ()
	{
		if (--this.requestCount == 0)
		{
			tagala.common.hideWait();
			if (!this.started) this.dispatch('onEnd');
		}
	}
});

tagala.Session.Responder =
{
	onCreate:function (request/* ,transport, headerJSON */)
	{
		if (Prototype.Browser.IE && tagala.config.noCache) request.url += (request.url.include('?') ? '&' : '?') + 'tagalaTS=' + Math.random();
		if (request.options.session) request.options.session.add();
		if (request.options.timeout) this.expireTimer = function ()
		{
			request.transport.abort();
		}.delay(request.options.timeout);
	},

	onComplete:function (request/* ,transport, headerJSON */)
	{
		if (request.options.session) request.options.session.release();
		if (this.expireTimer) window.clearTimeout(this.expireTimer);
	},

	onException:function (request, e)
	{
		var msg;
		switch (request.getStatus())
		{
			case 404:
				msg = request.url + ' not found.';
				break;
			default:
				msg = 'XHR Exception: "' + request.url + '"\n' + e.message;
		}
		(tagala.Debug.confirm || Prototype.emptyFunction)(msg);
	}
};
Ajax.Responders.register(tagala.Session.Responder);
