﻿/*
Section: CMS Elements
*/

var CMS = {};

CMS.Element = new Class({
	
	Extends: Events,

	register: function(name){
		CMS.elements.register(name, this);
	},

	fireEvent: function(type, args){
		this.parent(type, args);
		this.fireCmsEvent(type, args);
	},

	fireCmsEvent: function(type, args){
		CMS.elements.dispatchEvent(this.cmsName + '.' + type, $splat(args));
	}
});


CMS.Elements = new Class({
	initialize: function () {
		this.elements = {};
		this.listeners = {};
	},

	register: function (name, element) {
		element.cmsName = name;
		this.elements[name] = element;
		this.dispatchEvent(name + '.registered', []);
	},

	getElement: function (name, callback) {
		if (this.elements[name]) {
			callback(this.elements[name]);
		} else {
			this.addListener(name + '.registered', function (element) {
				callback(element);
			});
	}
	},

	call: function (target, args) {
		var p = target.split('.');
		var name = p[0];
		var methodName = p[1]
		var element = this.elements[name];

		if (element)
			element[methodName].apply(element, args);
	},

	addListener: function (target, callback) {
		this.listeners[target] = this.listeners[target] || [];
		this.listeners[target].push(callback);
	},

	dispatchEvent: function (name, args) {
		var listeners = this.listeners[name] || [];

		for (var i = 0; i < listeners.length; i++) {
			var listener = listeners[i];

			if ((typeof listener) == 'string') {
				this.call(listener, args);
			} else {
				var p = name.split('.');
				var name = p[0];
				var element = this.elements[name];

				listener.apply(this, [element].concat(args));
	}
		}
	}
});

CMS.elements = new CMS.Elements();


/*
Section: API
*/

var RsXmlApiRequest = new Class({

	options: {
		async: false,
		method: "get",
		urlEncoded: true,
		encoding: 'utf-8'
	},

	initialize: function () {
		this.request = new Request(this.options);
		return this;
	},
	
	sendGetRequest: function (requestUrl, queryParams) {
		var data = new Hash(queryParams);
		
		this.request.setOptions({url: requestUrl, data: data.toQueryString()});
		
		this.responseXml = this.request.send().response.xml;
		
		if (this.checkResponse()) {
			return this.responseXml.documentElement;
		} else {
			return null;
        }
	},

	sendPostRequest: function (requestUrl, postXmlDocument, queryParams) {
		//if (!postXmlDocument.xmlVersion): obsolete in FF 10.0. https://developer.mozilla.org/en/DOM/document.xmlVersion
		if (!postXmlDocument.createElement || postXmlDocument.createElement("foo").tagName == "FOO") {
			return this.sendPostRequestFormData(requestUrl, postXmlDocument, queryParams);
		} else {
			return this.sendPostRequestXML(requestUrl, postXmlDocument, queryParams);
    }
	},

	sendPostRequestXML: function (requestUrl, postXmlDocument, queryParams) {
		var queryString = queryParams ? '?' + Object.toQueryString(queryParams) : '';
		var xmlString = '';
		if (typeof XMLSerializer != "undefined") {
			xmlString = (new XMLSerializer()).serializeToString(postXmlDocument);
		} else {
			// Internet Explorer
			xmlString = postXmlDocument.xml;
		}
    
		this.request.setOptions({method: "post", url: requestUrl + queryString, data: xmlString, urlEncoded: false});
		this.request.setHeader("Content-type", "text/xml");
		
		this.responseXml = this.request.send().response.xml;
		
		if (this.checkResponse()) {
			return this.responseXml.documentElement;
		} else {
			return null;
		}
	},

	sendPostRequestFormData: function (requestUrl, requestData, queryParams) {
		var queryString = queryParams ? '?' + Object.toQueryString(queryParams) : '';

		this.request.setOptions({method: "post", url: requestUrl + queryString, data: requestData});
		this.responseXml = this.request.send().response.xml;

		if (this.checkResponse()) {
			return this.responseXml.documentElement;
		} else {
			return null;
    }
	},
	
	checkResponse: function () {
		var status = this.responseXml.documentElement.getAttribute("status");
		
		if (status != "ok") {
			alert("XML API Error: " + status + "\n" + this.responseXml.documentElement.textContent);
			return false;
    }
    
		return true;
	}
});


CMS.Api = new Class({

	Implements: Events,

	initialize: function (apiUrl) {
		this.url = apiUrl;
	},

	get: function (action, queryParams) {
		this.fireEvent('requestSent');
		var request = new RsXmlApiRequest();
		var result = request.sendGetRequest(this.url + '.' + action, queryParams || {});
		this.fireEvent('responseReceived', result);
		return result;
	},

	post: function (action, postData, queryParams) {
		this.fireEvent('requestSent');
		var request = new RsXmlApiRequest();
		var result = request.sendPostRequest(this.url + '.' + action, postData, queryParams);
		this.fireEvent('responseReceived', result);
		return result;
	}
});


/*
Section: Helpers
*/

function getParentIFrame (element) {
	var window = element.getWindow();
	var frames = window.parent.document.getElements('iframe').filter(function (frame) {
		return frame.contentWindow == window;
	});
	return frames[0] || null;
}

function getLastScriptElement () {
	return Script.getElement();
}

function getParentOfLastScriptElement () {
	return Script.getParent();
}

function attachData (data) {
	var element = getParentOfLastScriptElement();
	element.store('data', data);
}

function fetchData (element) {
	return element.retrieve('data') || {};
}

function getSearchLocationWithParam (key, value) {
	return new URI(document.location.href).setData(key, value).toString();
}


Script = {

	currentElement: null,

	getElement: function () {
		if (this.currentElement)
			return this.currentElement;

		var elements = document.getElementsByTagName('script');
		var element = document.id(elements[elements.length - 1]);
		return element;
	},

	getParent: function () {
		return this.getElement().getParent();
	},

	execute: function (element) {
		var win = element.getWindow() || window;
		currentElement = element;
		win.eval(element.get('text'));
		currentElement = null;
	}	
}
