if (typeof Fox == 'undefined') {
	Fox = {};
}

Fox.Api = {
	domain: '',
	script: 'api.php'
};

/**
 * @param string method - Method of HTTP request. Supported methods are 'get' and 'post'.
 * @param string section - API section which you want to use.
 * @param string action - An action of API section which you want to execute
 * @param hash options - All that you may need to configure API call:
 * 
 * 'params' - optional property which consists of key-value pairs which would be added to HTTP query (URL if you use get and post body otherwise)
 * 'onSuccess' - callback which would be called in case when API returns 'true' status (request was succeed)
 * 'onFailure' - callback which woulb be called in case when API returns 'false' status (request was failed by some reasons)
 * 'xhr' - XMLHttpRequest's callbacks (each callback must be passed as separate property of 'xhr' hash):
 * 
 * onCreate			Triggered when the Ajax.Request object is initialized. This is after the parameters and the URL have been processed, but before first using the methods of the XHR object.
 * onComplete		Triggered at the very end of a request's life-cycle, once the request completed, status-specific callbacks were called, and possible automatic behaviors were processed.
 * onException		Triggered whenever an XHR error arises. Has a custom signature: the first argument is the requester (i.e. an Ajax.Request instance), the second is the exception object.
 * onFailure		Invoked when a request completes and its status code exists but is not in the 2xy family. This is skipped if a code-specific callback is defined, and happens before onComplete.
 * onInteractive	(Not guaranteed) Triggered whenever the requester receives a part of the response (but not the final part), should it be sent in several packets.
 * onLoaded			(Not guaranteed) Triggered once the underlying XHR object is setup, the connection open, and ready to send its actual request.
 * onLoading		(Not guaranteed) Triggered when the underlying XHR object is being setup, and its connection opened.
 * onSuccess		Invoked when a request completes and its status code is undefined or belongs in the 2xy family. This is skipped if a code-specific callback is defined, and happens before onComplete.
 * onUninitialized	(Not guaranteed) Invoked when the XHR object was just created.
 * onXYZ			With XYZ being an HTTP status code for the response. Invoked when the response just completed, and the status code is exactly the one we used in t he callback name. Prevents execution of onSuccess / onFailure. Happens before onComplete.
 */
Fox.Api.call = Class.create({
	initialize: function(method, section, action, options) {
		var prototypeOptions = {};
		if (method == 'get') {
			prototypeOptions.method = 'get';
			if (section == 'secure') {
				prototypeOptions.parameters = 'fox_hash=' + action;
			} else {
				prototypeOptions.parameters = 'section=' + section + '&action=' + action;
			}
			if (options && options.params) {
				prototypeOptions.parameters += '&' + Object.toQueryString(options.params);
			}
		} else if (method == 'post') {
			prototypeOptions.method = 'post';
			if (section == 'secure') {
				prototypeOptions.postBody = 'fox_hash=' + action;
			} else {
				prototypeOptions.postBody = 'section=' + section + '&action=' + action;
			}
			if (options && options.params) {
				prototypeOptions.postBody += '&' + Object.toQueryString(options.params);
			}
		} else {
			throw new Error('Unknown method ' + method);
		}
		var url = location.protocol + '//' + (Fox.Api.domain ? Fox.Api.domain : location.host) + '/' + Fox.Api.script;
		
		if ('xhr' in options) {
			for (var property in options.xhr) {
				if (property == 'onSuccess') {
					this._customXhrOnSuccess = options[property];
				} else if (property.match(/^on[A-Z]/)) {
					prototypeOptions[property] = options[property];
				}
			}
		}
		
		prototypeOptions.onSuccess = this._onSuccess.bind(this);
		this._customOnSuccess = options.onSuccess || false;
		this._customOnFailure = options.onFailure || false;
		new Ajax.Request(url, prototypeOptions);
	},
	
	_onSuccess: function(transport) {
		var data = transport.responseText.evalJSON();
		if (data.status) {
			if (this._customOnSuccess) {
				this._customOnSuccess(data.response);
			}
			
			if (this._customXhrOnSuccess) {
				this._customXhrOnSuccess(transport);
			}
		} else {
			if (this._customOnFailure) {
				this._customOnFailure(data.response);
			}
		}
	}
});

Fox.Api.secureCall = Class.create({
	initialize: function(hash, options, method) {
		if (!method) {
			this.method = 'get';
		}
		if (!hash) {
			console.log('Api secure call: missing hash');
			return false;
		}
		this.hash = hash;
		if (options) {
			this.options = options;
		} else {
			this.options = {};
		}
	},
	call: function(params) {
		if (params) {
			this.options.params = params;
		}
		new Fox.Api.call(this.method, 'secure', this.hash, this.options);
	}
});
