/**
 *  This script is build for handling ajax requests for the EMotioned Framework.
 *  It's possible to build your complete website with ajax now. Including the 
 *  handling of file uploads etc.
 */

/**
 *  @var    formElement (represents the <form> tag where we are working on.
 */
var formElement=false;

/**
 *  @var    fileUploadId (contains a unique number foreach fileupload)
 */
var fileUploadId = 99999;

/**
 *  Method to process a complete form. This method will make an asynchronous 
 *  call to the component wich is responsible for handling the form data.
 *
 *
 *  @param  string  formID                  (for example: <form id="login"></form>
 *  @param  string  callBackMethod          (for example: "doLogin()"
 *  @param  string  url (optional)          (could be antoher component).
 *  @param  string  command (optional)      (extra command by processing a form).
 *  @return array   JSon array.
 */
function processForm(formID, callBackMethod, url, command)
{
    if(!formID) return false;
    if(!callBackMethod) return false;
    
    // Get the formID append a # to it.
    formID = "#" + formID;
    
    // Get the url from the form action parameter.
    if(!url) url = $(formID).attr('action');
    if(!url)
    {
        alert('Error no form action detected. Did you supply the correct formID?');
    }
    
    // Append the hidden form field cpa (so that the framework knows it's 
    // handling an ajax / json request.
    $(formID).append("<input id='emotioned_temp_cpa_var' type='hidden' name='cpa' value='1'/>");
    if(command) $(formID).append("<input id='emotioned_temp_command_var' type='hidden' name='"+command+"' value='1'/>");
    
    // Serialize the complete form
    var data = $(formID).serialize();
    
    // Now destroy the CPA hidden variable. and the temporary command parameters
    // if there are any ofcourse.
    $("#emotioned_temp_cpa_var").remove();
    if(command) $("#emotioned_temp_command_var").remove();
    
    // Now process the request.
    $.post(url, data, function(data)
    {
        // The callback method should be implemented in the component itself.
        callBackMethod(data);
    }, "json");
}

/**
 *  Method to process a form field. This method is identical to the processForm method
 *  Except for one difference, we are here processing just ONE form field.
 *
 *  @param  string  formFieldID             (for example: <select id="mylist"></form>
 *  @param  string  callBackMethod          (for example: "saveList()"
 *  @param  string  url (optional)          (could be antoher component).
 *  @param  string  command (optional)      (extra command by processing a formfield.).
 *  @return array   JSon array.
 */
function processFormField(formFieldID, callBackMethod, url, command)
{
    // Check if the formfield ID and the callback method where supplied.
    // If not we will cancel the transaction.
    if(!formFieldID) return false;
    if(!callBackMethod) return false;
    
    // Get the formID append a # to it.
    formFieldID = "#" + formFieldID;
    
    if(!url)
    {
	    findForm($(formFieldID));
	    // Get the action from the form field.
	    url = formElement.attr('action');
	}    
    
    if(!url) alert('error, no url found by processing the form field');
    
    // Serialize the data.
    var data = $(formFieldID).serialize();
    
    // Append the special cpa parameter to the data.
    data += "&cpa=1";
    
    // Check if we have to add a command aswell.
    if(command) data += "&"+command+"=1";
    
    // Now process the request.
    $.post(url, data, function(data)
    {
        // The callback method should be implemented in the component itself.
        callBackMethod(data);
    }, "json");
    
    // Reset the formElement
    formElement = false;
}

/**
 *  Method to process a fileupload. This method will create a hidden iframe of
 *  1x1 pixels (not visible for the user). This IFrame will be used to submit 
 *  the fileupload. It's not possible to upload a file with an ajax call. 
 *  Because this is forbidden.
 *
 *  @param  string  formFieldID             (for example: <input type="file" name="myfile"/>
 *  @param  string  callBackMethod          (for example: "photoUploaded()"
 *  @param  string  url                     (could be antoher component).
 *  @param  string  command (optional)      (extra command by processing a formfield.).
 *  @return array   JSon array.
 */
function processFileUpload(formFieldID, callBackMethod, command)
{
    // Check if the formfield ID and the callback method where supplied.
    // If not we will cancel the transaction.
    if(!formFieldID) return false;
    if(!callBackMethod) return false;
    
    // Update the fileupload ID.
    fileUploadId++;
    
    // Get the formID append a # to it.
    formFieldID = "#" + formFieldID;
    findForm($(formFieldID));
    
    // Change the target of the formElement, we want it to 
    // process to an iframe.
    currentTarget = formElement.attr('target');
    
    // Construct a unique name for the frame.
    frameName = "upload_target" + fileUploadId;
    
    // Get the current action / url of the form.
    currentAction = formElement.attr('action');
    
    // Alright, now we are manipulating the action string a bit, we add the following flags to the url:
    // *cpf = 1 component process fileupload
    // *callback = ...  the callback function that will be triggered when the fileupload is finished.
    // *file_upload_id = .. the id to the hidden iframe.
    formElement.attr('action', currentAction + "&cpf=1&callback="+callBackMethod+"&file_upload_id="+fileUploadId);
    
    // Set the name of the frame in the target of the form.
    formElement.attr('target', frameName);
    
    // Construct an 1px iframe, to perform the upload.
    $("body").append('<iframe style="position:absolute;" id="'+frameName+'" name="'+frameName+'" frameborder="0" height="0" width="0" src="#"></iframe>');
    
    // Process the form.
    formElement.submit();
    
    // Change the action aswell.
    formElement.attr('action', currentAction);
    
    // Reset the target of the form.
    formElement.attr('target', '_self');
    
    // Set the found formelement on false again.
    formElement = false;
    
    // All done.
    return;
}

/**
 *  Method to stop uploading a file. This is a nice method to cancel 
 *  a fileupload (for example if someone has selected a file of 50Mb instead of 100kb).
 *  
 *  @param integer  fileUploadId
 */
function processStopFileUpload(fileUploadId)
{
    // Construct a unique name for the frame.
    frameName = "#upload_target" + fileUploadId;
    $(frameName).remove();
}

/**
 *  Recursive method to find the form whereto this formfield belongs.
 *  @param  JQuery object
 *  @return JQuery object
 */
function findForm(el)
{
    // Get the parent from the supplied element.
    var p = el.parent();
    
    // Check if we have found the form. Otherwise goto the next parent.
    if(p.attr('action') && p.attr('action') != null && p.attr('action') != '')
    {
        formElement = p;
    }
    else
    {
        findForm(p);
    }
}

/**
 *  Method to remove the hidden iframe after the upload has been completed.
 */
function removeFileUploadFrame(upload_id)
{
    frameName = "#upload_target" + upload_id;
    $(frameName).remove();
}