/*

Some of this code is part of the Flash / JavaScript Integration Kit:
http://www.macromedia.com/go/flashjavascript/

Created by:

Christian Cantrell
http://weblogs.macromedia.com/cantrell/
mailto:cantrell@macromedia.com

Mike Chambers
http://weblogs.macromedia.com/mesh/
mailto:mesh@macromedia.com

Macromedia

***** Added 1/17/06 by Geoff Stearns (geoff@deconcept.com):

This version of the JS Integration kit requires swfobject 1.4.4 or later
Download SWFObject at http://blog.deconcept.com/swfobject/

the swfobject.js file must be linked before this file is linked.

SWFObject is (c) 2006 Geoff Stearns and is released under the MIT License:
http://www.opensource.org/licenses/mit-license.php

*/

/**
 * The FlashSerializer serializes JavaScript variables of types object, array, string,
 * number, date, boolean, null or undefined into XML. 
 */

/**
 * Create a new instance of the FlashSerializer.
 * useCdata: Whether strings should be treated as character data. If false, strings are simply XML encoded.
 */
function FlashSerializer(useCdata){
  this.useCdata = useCdata;
}

/**
 * use encodeURIComponent() if the browser supports it, otherwise use escape()
 */
FlashSerializer.prototype.encodeVal = function(val){
  if(document.encodeURIComponent) {
    return encodeURIComponent(val);
  }
  return escape(val);
}

/**
 * Serialize an array into a format that can be deserialized in Flash. Supported data types are object,
 * array, string, number, date, boolean, null, and undefined. Returns a string of serialized data.
 */
FlashSerializer.prototype.serialize = function(val){
  var result = new Array();
  switch(typeof val){
    case 'undefined':
      result[0] = 'undef';
      break;
    case 'string':
      result[0] = 'str';
      result[1] = this.encodeVal(val);
      break;
    case 'number':
      result[0] = 'num';
      result[1] = val.toString();
      break;
    case 'boolean':
      result[0] = 'bool';
      result[1] = val.toString();
      break;
    case 'object':
      if (val == null) {
        result[0] = 'null';
      } else if (val.getTime) {
        result[0] = 'date';
        result[1] = this.encodeVal(val.getTime());
      } else { // array or object
        try {
          result[0] = 'xser';
          result[1] = this.encodeVal(this._serializeXML(val));
        }catch (e){}
      }
      break;
    default:
      // do nothing
  }
  return result;
}

/**
 * Private
 */
FlashSerializer.prototype._serializeXML = function(obj)
{
    var doc = new Object();
    doc.xml = '<fp>'; 
    this._serializeNode(obj, doc, null);
    doc.xml += '</fp>'; 
    return doc.xml;
}

/**
 * Private
 */
FlashSerializer.prototype._serializeNode = function(obj, doc, name){
  switch(typeof obj) {
    case 'undefined':
      doc.xml += '<undf'+this._addName(name)+'/>';
      break;
    case 'string':
      doc.xml += '<str'+this._addName(name)+'>'+this._escapeXml(obj)+'</str>';
      break;
    case 'number':
      doc.xml += '<num'+this._addName(name)+'>'+obj+'</num>';
      break;
    case 'boolean':
      doc.xml += '<bool'+this._addName(name)+' val="'+obj+'"/>';
      break;
    case 'object':
      if (obj == null) {
        doc.xml += '<null'+this._addName(name)+'/>';
      } else if (obj.getTime) {
        doc.xml += '<date'+this._addName(name)+'>'+obj.getTime()+'</date>';
      } else if (obj.length != undefined) {
        doc.xml += '<array'+this._addName(name)+'>';
        for (var i = 0; i < obj.length; ++i) {
          this._serializeNode(obj[i], doc, null);
        }
        doc.xml += '</array>';
      } else {
        doc.xml += '<obj'+this._addName(name)+'>';
        for (var n in obj) {
          if (typeof(obj[n]) == 'function') {
            continue;
          }
        this._serializeNode(obj[n], doc, n);
        }
        doc.xml += '</obj>';
      }
      break;
    default:
      // do nothing
  }
}

/**
 * Private
 */
FlashSerializer.prototype._addName= function(name){
  if (name != null) {
    return ' name="'+name+'"';
  }
  return '';
}

/**
 * Private
 */
FlashSerializer.prototype._escapeXml = function(str){
  if (this.useCdata) {
    return '<![CDATA['+str+']]'
  }
}