var JsonForm = new Class({
	Implements: [Options, Events, Log],
	Extends: Form,
	
	// Variables
	url: null,
	handlers: null,
	request: null,
	values: [],
	
	// Classes
	application: null,
	
	/*
	 * Initialize
	 */
	initialize: function(element, url, handlers, options)
	{
		//this.enableLog();
		//this.disableLog();
		this.log("JsonForm::initialize(" + element + ", " + options + ")");
		
		// Invoke parent class constructor
		this.parent(element, options);
		
		// Set variables
		this.url = url;
		this.handlers = handlers;
		this.application = new Application();
	},


	/*
	 * Reset
	 */
	reset: function()
	{
		this.log("Form::reset()");

		// Invoke parent method
		this.parent();

		// Reset values
		this.values = [];
	},

	/*
	 * Submit
	 */
	submit: function()
	{
		this.log("JsonForm::submit()");

		// Start param string
		var paramsString = "{";
		
		// Enable form elements
		this.elements.each(function(element, index) {
			
			var name = element.name;
			var input;
			switch(element.element.type)
			{
				case 'checkbox':
					input = element.element.checked;
					break;
				
				default:
					input = element.element.value;
					break;
			}
			
//			if(index == 0) paramsString += '{';

			input = JSON.encode( input );

			//var param = '"' + name + '": "' + input + '"';
			var param = '"' + name + '": ' + input;
			paramsString += param;
			
			if(index < this.elements.length - 1) paramsString += ',';

			this.log("paramsString: " + paramsString);
//			if(index == this.elements.length - 1) paramsString += '}';
			
		}, this);

		if(this.values.length > 0 && paramsString.length > 1) paramsString += ',';

		// Extra values
		this.values.each(function(element, index) {

//			if(paramsString.length == 0) paramsString += '{';

			//this.log("typeof(" + element.value + ")" + typeof(element.value));
			//this.log("JSON.encode(" + element.value + ")" + JSON.encode(element.value));

			var value = JSON.encode( element.value );
//			var value;
//
//			switch(typeof(element.value))
//			{
//				case "object":
//					value = JSON.encode(element.value);
//					break;
//				default:
//					value = element.value;
//					break;
//			}

//			var param = '"' + element.key + '": "' + value + '"';
			var param = '"' + element.key + '": ' + value;
			paramsString += param;

			if(index < this.values.length - 1) paramsString += ',';

			this.log("paramsString: " + paramsString);
//			if(index == this.values.length - 1) paramsString += '}';

		}, this);

		// Add end of string
		paramsString += '}';

		this.log("final paramsString: " + paramsString);
		
		var params = JSON.decode(paramsString);

		/*
		this.request = new Request.JSON({
			url: this.url,
			onRequest: this.onRequest.bind(this),
			onSuccess: this.onSuccess.bind(this),
			onFailure: this.onFailure.bind(this),
			onException: this.onException.bind(this)
		});
		
		// Send request
		this.request.send("JSONData=" + JSON.encode(params));
		*/

		var requestData = {
			url: this.url,
			params: params,
			link: 'cancel',
			onRequest: this.onRequest.bind(this),
			onSuccess: this.onSuccess.bind(this),
			onFailure: this.onFailure.bind(this),
			onException: this.onException.bind(this)
		}

		this.application.request(requestData);
	},
	
	/*
	 * Cancel
	 */
	cancel: function()
	{
		this.log("JsonForm::cancel()");
		
		if(this.application.jsonRequest.isRunning())
		{
			// Cancel request			
			this.application.jsonRequest.cancel()
			
			// Enable form
			this.enable();
			
			// Hide load state
			this.hideLoadState();
		}
	},

	/*
	 * Add value
	 */
	addValue: function(key, value)
	{
		this.log("JsonForm::addValue(" + key + ", " + value + ")");

		var keyIndex = false;
		this.values.each(function(element, index) {

			if(element.key == key)
			{
				keyIndex = index;
			}

		}.bind(this));

		if(key && value)
		{
			var element = {key: key, value: value};

			// Update
			if(keyIndex !== false)
			{
				this.log("update");
				this.values[keyIndex] = element;
			}
			// Add
			else
			{
				this.log("add");
				this.values.include(element);
			}
		}

		this.log("this.values.length: " + this.values.length);
	},
	
	/*
	 * JSON handlers
	 */
	onRequest: function()
	{
		this.log("JsonForm::onRequest()");
		
		this.fireEvent('onRequest');
		
		if(this.handlers.onRequest)
		{
			this.handlers.onRequest.attempt([], this);
		}
	},
	
	onSuccess: function(jsonObject)
	{
		this.log("JsonForm::onSuccess(" + jsonObject + ")");
		
		this.fireEvent('onSuccess');
		
		// Default actions
		this.hideLoadState();
		this.enable();
		
		// User handler
		if(this.handlers.onSuccess)
		{
			this.handlers.onSuccess.attempt([jsonObject], this);
		}
	},
	
	onFailure: function(xhr)
	{
		this.log("JsonForm::onFailure(" + xhr + ")");
		
		this.fireEvent('onFailure');
		
		// Show failure message
		this.cancel();
		
		// Show form error
//		if(this.formErrorMessage)
//		{
//			this.formErrorMessage.show();
//		}

		this.log("this.handlers.onFailure: " + this.handlers.onFailure);

		// User handler
		if(this.handlers.onFailure)
		{
			this.handlers.onFailure.attempt([xhr], this);
		}
	},
	
	onException: function(headerName, value)
	{
		this.log("JsonForm::onException(" + headerName + ", " + value + ")");
		
		this.fireEvent('onException');
		
		// Show exeption message
		this.cancel();
		
		// Show form error
		if(this.formErrorMessage)
		{
			this.formErrorMessage.show();
		}
		
		// User handler
		if(this.handlers.onException)
		{
			this.handlers.onException.attempt([headerName, value], this);
		}
	}

});
