/**
 * 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;}

/**
 * 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(args) {
    var qs = new String();
    for (var i = 0; i < args.length; ++i) {
        switch(typeof(args[i])) { 
            case 'undefined': qs += 't'+(i)+'=undf';
                break;
            case 'string': qs += 't'+(i)+'=str&d'+(i)+'='+escape(args[i]);
                break;
            case 'number': qs += 't'+(i)+'=num&d'+(i)+'='+escape(args[i]);
                break;
            case 'boolean': qs += 't'+(i)+'=bool&d'+(i)+'='+escape(args[i]);
                break;
            case 'object':
                if (args[i] == null) { qs += 't'+(i)+'=null'; }
                else if (args[i] instanceof Date) {
                    qs += 't'+(i)+'=date&d'+(i)+'='+escape(args[i].getTime()); }
                else // array or object 
                    { try  { qs += 't'+(i)+'=xser&d'+(i)+'='+escape(this._serializeXML(args[i])); }
                    catch (exception) { throw new Exception("FlashSerializationException",                                            "The following error occurred during complex object serialization: " + exception.getMessage()); } }
                 break;
            default: throw new Exception("FlashSerializationException",                                    "You can only serialize strings, numbers, booleans, dates, objects, arrays, nulls, and undefined."); }

        if (i != (args.length - 1)) { qs += '&'; } }

    return qs; }


/**
 * 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 instanceof Date) { doc.xml += '<date'+this._addName(name)+'>'+obj.getTime()+'</date>'; }
            else if (obj instanceof Array) { 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: throw new Exception("FlashSerializationException", "You can only serialize strings, numbers, booleans, objects, dates, arrays, nulls and undefined");
            break; } }

/**
 * 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+']]>';
    else return str.replace(/&/g,'&amp;').replace(/</g,'&lt;'); }

