O3Global.Forms = new function()
{
  // Constants
  var TYPE_UNKNOWN      = 0;
  var TYPE_TEXT         = 1;
  var TYPE_RADIO        = 2;
  var TYPE_CHECKBOX     = 3;
  var TYPE_SELECT       = 4;
  var TYPE_RADIO_CHECK  = 5;

  // Form serializer (form -> array)
  function serializeForm(frmSerialize)
  {
    // Check for form
    if(!frmSerialize)
      return null;

    // Generic & radio holder
    var aData  = new Array();
    var aRadio = new Array();

    // Loop elements
    for(var sElement in frmSerialize.elements)
    {
      // Fetch element
      var hElement = frmSerialize.elements[sElement];
      if(hElement == null)
        continue;

      // Define element type
      var iType = TYPE_UNKNOWN;
      if(hElement.type != null)
      {
        if(hElement.type == 'text' || hElement.type == 'textarea' || hElement.type == 'hidden' || hElement.type == 'password')
          iType = TYPE_TEXT;
        else if(hElement.type == 'radio')
          iType = TYPE_RADIO_CHECK;
        else if(hElement.type == 'checkbox')
          iType = TYPE_CHECKBOX;
        else if(hElement.type == 'select-one' || hElement.type == 'select-multiple')
          iType = TYPE_SELECT;
      }

      // Special radio handler
      if(hElement[0] != null && hElement[0].type == 'radio')
        iType = TYPE_RADIO;

      // Skip unknown
      if(iType == TYPE_UNKNOWN)
        continue;

      // Skip disabled
      if(hElement.disabled || (iType == TYPE_RADIO && hElement[0].disabled))
        continue;

      // Skip unchecked radio checks
      if(iType == TYPE_RADIO_CHECK && !hElement.checked)
        continue;

      // Set proper name
      if(hElement.name)
        sElement = hElement.name;
      else if(hElement[0].name)
        sElement = hElement[0].name;

      // Skip already processed radio
      if(iType == TYPE_RADIO)
      {
        if(aRadio[sElement])
          continue;
        else
          aRadio[sElement] = true;
      }

      // Handle types
      switch(iType)
      {
        case TYPE_RADIO:
          for(var i = 0; i < hElement.length; i++)
          {
            if(hElement[i].checked)
            {
              aData[sElement] = hElement[i].value;
              break;
            }
          }
          break;
        case TYPE_CHECKBOX:
          if(hElement.checked)
            aData[sElement] = hElement.value;
          break;
        default:
         // Add value
         aData[sElement] = hElement.value;
         break;
      }
    }

    // Return data
    return aData;
  }

  // Toggle form
  function toggleForm(frmToggle, bDisable)
  {
    // Skip if no form
    if(!frmToggle)
      return;

    // Loop all elements
    for(var i = 0; i < frmToggle.elements.length; i++)
    {
      // Fetch element
      var hElement = frmToggle.elements[i];
      if(hElement == null)
        continue;

      // Toggle element
      if(hElement.disabled != null)
        hElement.disabled = bDisable;
    }
  }

  // Enable form
  function enableForm(frmEnable)
  {
    // Call toggle
    toggleForm(frmEnable, false);
  }

  // Disable form
  function disableForm(frmDisable)
  {
    // Call toggle
    toggleForm(frmDisable, true);
  }

  // Fetch value of a radio box
  function getRadioValue(oRadio)
  {
    // Check for array or singular
    if(oRadio[0])
    {
      for(var i = 0; i < oRadio.length; i++)
      {
        if(oRadio[i].checked)
          return oRadio[i].value;
      }
    }
    else
      return oRadio.value;
  }

  // Bind public functions
  this.serializeForm = serializeForm;
  this.enableForm    = enableForm;
  this.disableForm   = disableForm;
  this.getRadioValue = getRadioValue;
}