/**
* Basic form object (editing and adding)
*/
var Form = function(action, onreturn, title, oncancel, description)
{
	// string
	this.action = action;
	// array
	this.fieldset = new Array();
	// array
	this.buttons = new Array();

	this.onreturn = onreturn;
	this.oncancel = oncancel;

  this.title = title;
	// submit button label
	this.label_submit = 'Submit';
  
  this.summarise = false;

	this.dom_root = createElement('form', action.replace('/', '_'));
	this.dom_root.isSubmitted = false;
	this.dom_root.id = 'mainform';

  if(title)
  {
		var dom_legend = createElement('div');
		dom_legend.className = 'legend';
    dom_legend.innerHTML = title;
    this.dom_root.appendChild(dom_legend);
  }
	
	if(description)
	{
		var dom_description = createElement('div','formdescription');
		dom_description.innerHTML = description;
		this.dom_root.appendChild(dom_description);
	}

	// Button
	this.button;
  
	if(oncancel!=null)
	{
		this.cancelButton;
	}
	
	this.getData = function()
	{
		// Save any TinyMCE content that might exist on the page.
		if(typeof(tinyMCE) !== 'undefined')
		{
			tinyMCE.triggerSave();
		}
		var data = '';
		for(fieldset in this.fieldset)
		{
			var fields = this.fieldset[fieldset].getFields();
			for(field in fields)
			{
				//special handling for multiple select field.
				if(fields[field].type == 'SelectField' && fields[field].mode == 'multi')
				{
					var selectedOptions = fields[field].getSelected();
					for(itemkey in selectedOptions)
					{
						data += '&' + fields[field].getName() + '[]=' + selectedOptions[itemkey];
					}
				}
				else if (fields[field].dom_input || fields[field].type == 'SeperatedDateField')
				{
					data += '&' + fields[field].getName() + '=' + fields[field].getValue();
				}
			}
		}
		return data.substring(1);
	}
	
	var ref = this;
	this.onfail = function(data)
	{
		ref.button.enable();
    
    if(oncancel!=null)
    {
      ref.cancelButton.enable();
    }
    
    // Clear the errors displayed against every field before processing which fields need error messages displayed.
    for(var x = 0; x < ref.fieldset.length; x++)
    {
    	for(var y = 0; y < ref.fieldset[x].fields.length; y++)
    	{
    		if(ref.fieldset[x].fields[y].unsetError)
    		{
    			ref.fieldset[x].fields[y].unsetError();
    		}
    	}
    }
  	
    if(data && data['fields'])
    {
			for(var field in data['fields'])
			{
		    var currentField = ref.getField(field);
		    if(currentField)
		    {
		      if(data['fields'][field]['error'])
		  		{
			    	if(currentField.setError)
			    	{
			      	currentField.setError(data.fields[field].message);			    	}
			  	}
				}
      }
    }
	}

  this.setSubmitLabel = function(label)
  {
    this.label_submit = label;
  }

	// If this form contains a file field that is currently uploading, returns this field, or false otherwise
	this.hasActiveUpload = function()
	{
		// Go through the form looking for file upload fields
		for(fieldset in ref.fieldset)
		{
			var fields = ref.fieldset[fieldset].getFields();
			for(field in fields)
			{
				if(fields[field].dom_input && fields[field].dom_input.type == 'file')
				{
					// See if an upload is in progress for this field
					if(fields[field].uploadInProgress())
					{
						return fields[field];
					}
				}
			}
		}
		
		// If we got here, there are no active uploads
		return false;
	}
	
	this.submit = function()
	{
		ref.button.disable ();
		var field;
		if(field == ref.hasActiveUpload())
		{
			// Don't submit until the upload is complete.
			ref.dom_root.isSubmitted = true;
			field.dom_root.hook_complete = function()
			{
				ref.submit();
			}
			return false;
		}

		// If a field is marked as required and the field does not have a value, the form cannot be submitted.
		for(fieldset in ref.fieldset)
		{
			var fields = ref.fieldset[fieldset].getFields();
			for(field in fields)
			if
			(
				(fields[field].getType() == 'DateField' && fields[field].getRequired() && fields[field].getValue() == 0) ||
				(fields[field].getRequired() && fields[field].getValue() === '')
			)
			{
				notifier.notify('error', 'You must supply a value for the ' + fields[field].getLabel() + ' field');
				ref.button.enable();
				return false;
			}
		}
		var ticket = requestProcess.add(new Request ('POST', '/api/'+ref.action, ref.getData(), ref.onreturn, ref.onfail));
		return false;
	}
	
	// I think both of these are needed to get this working in Firefox and Internet Explorer
	this.dom_root.onsubmit = this.submit;
	window.onsubmit = this.submit;

	// doesn't work
	this.setOnFail = function(onFail)
	{
		this.onFail = onFail;
	}
	
	this.addFieldset = function(fieldset)
	{
		fieldset.ref_parent = this;
		this.fieldset[this.fieldset.length] = fieldset;
	}
	
	this.addField = function(field)
	{
		if(this.fieldset.length == 0)
		{
			this.fieldset[0] = new Fieldset();
			this.fieldset[0].ref_parent = this;
		}
		this.fieldset[0].addField(field);
	}

	this.addFields = function(fields)
	{
		if(this.fieldset.length == 0)
		{
			this.fieldset[0] = new Fieldset();
			this.fieldset[0].ref_parent = this;
		}
		this.fieldset[0].addFields(fields);
	}
	
	this.getField = function(name)
	{
		// Need to go through all of the fieldsets in the form, then through each of the fields in these
		for(fieldset in this.fieldset)
		{
			for(field in this.fieldset[fieldset].fields)
			{
				if(this.fieldset[fieldset].fields[field].getName() == name)
				{
					return this.fieldset[fieldset].fields[field];
				}
			}
		}
		return false;
	}
	
	this.removeField = function(name)
	{
		for(field in this.fields)
		{
			if(this.fields[field].getName() == name)
			{
				this.fields[field] = null;
				return true;
			}
		}
		return false;
	}
	
	this.reset = function(oncancel) //depreciated ... i think.
	{
		for(field in this.fields)
		{
			this.fields[field].clear();
		}
		oncancel();
		return false;
	}
  
  // I think both of these are needed to get this working in Firefox and Internet Explorer
  this.dom_root.onreset = this.reset;
  window.onreset = this.reset;

	this.draw = function()
	{
		removeAllChildren(this.dom_root);
		for(fieldset in this.fieldset)
		{
			this.dom_root.appendChild(this.fieldset[fieldset].draw());
			this.dom_root.appendChild(createElement('div','clear'));
		}

		var buttons = createElement('div','buttons');
		for(button in this.buttons)
		{
			buttons.appendChild(this.buttons[button].draw());
		}
		this.button = new ImageButton(this.label_submit, this.submit, true, 'button submit');
		buttons.appendChild(this.button.draw());
		if(oncancel!=null)
		{
			this.cancelButton = new ImageButton('Cancel', this.oncancel, true, 'button cancel');
			buttons.appendChild(this.cancelButton.draw());
		}
		buttons.appendChild(createElement('div','clear'));
		this.dom_root.appendChild(buttons);
		this.dom_root.appendChild(createElement('div','clear'));

		return this.dom_root;
	}
	
	//set whether to summarise entered data - will css hide all fields that are empty..
	this.setSummariseMode = function(value)
	{
		this.summarise = value;
	}

	/*
	 * Hides blank fields so that the order can be reviewed before submitting
	 * Should set summarise mode to true, rather than calling this function from outside the object
	 */
	this.summariseOrder = function()
	{
		//hide all the blank fields..
		
		var i = 0;
		for (field in ref.fields)
		{
			var regExpHasValue = new RegExp("[A-Za-z0-9]+", "i");

			if(this.fields[field].dom_input.type == 'text')
			{
				if(regExpHasValue.test(this.fields[field].dom_input.value, "i") == true)
				{
					
					this.fields[field].dom_root.style.border = '2px solid #87AFBF';
				}
				else
				{
					this.fields[field].dom_root.style.display = 'none';
				}
			}
		}
		notifier.notify('info','Please review your order before submitting.');
		this.setSummariseMode(false);
	}
	this.showField = function(name)
	{
		// Go through all of the fieldsets trying to show the field
		for(var x in this.fieldset)
		{
			if(this.fieldset[x].showField(name))
			{
				// Field found and marked as visible, redraw the form, then there's nothing more to do
				this.draw();
				return;
			}
		}
	}
	
	this.hideField = function(name)
	{
		for(var x in this.fieldset)
		{
			if(this.fieldset[x].hideField(name))
			{
				// Field found and marked as hidden, redraw the form, then there's nothing more to do
				this.draw();
				return;
			}
		}
	}
	
	this.getDomRoot = function()
	{
		return this.dom_root;
	}
}

/**
* Prototype form input, implements basic form input functions
* Note that values that don't have a coresponding override in the extending JS function will be static
*/
var FormField = function()
{
	// string
	this.label='';
	// string
	this.description='';
	// string
	this.name='';
  // string
  this.id='';
	// string (default, could be something else)
	this.value = '';
	// string
	this.hint = '';
	// boolean
	this.required = false;
	// dom element
	this.dom_label='';
	// tab order
	this._tab_order=null;
	
	// Should the control be drawn or not.
	this.hidden = false;
	
	this.type=null;
	
	this.getLabel = function()
	{
		return this.label;
	}
	this.setLabel = function(label)
	{
		this.label = label;
	}
	this.getHint = function()
	{
		return this.hint;
	}
	this.setHint = function(hint)
	{
		this.hint = hint
	}

	this.setTabOrder = function(tab_order)
	{
		this._tab_order = tab_order;
	}
	this.getTabOrder = function()
	{
		return this._tab_order;
	}

  this.setID = function(id)
  {
    this.id = id;
  }
  this.getID = function()
  {
    return this.id;
  }
	
	this.setName = function(name)
	{
		this.name = name;
	}
	this.getName = function()
	{
		return this.name;
	}
	
  this.setDescription = function(description)
  {
      this.description = description;
  }
  this.getDescription = function()
  {
       return this.description;
  }
  
	this.getType = function()
	{
		return this.type;
	}

	this.clear = function()
	{
		this.value = '';
	}

	this.getRequired = function()
	{
		return this.required;
	}
	
	this.setRequired = function(required)
	{
		this.required = required;
	}
	
	this.getHidden = function()
	{
		return this.hidden;
	}
	
	this.setHidden = function(hidden)
	{
		this.hidden = hidden;
	}
	
	this.getDomRoot = function()
	{
		return this.dom_root;
	}
}
