var RestorerIF = Class.create({
initialize: function() { }
});

// Generic interface
RestorerIF.restore = function(oRestorerImpl) {
	var T = oRestorerImpl.GetType();
	if (T == "int") return oRestorerImpl.RestoreInt();
	if (T == "int64_t") return oRestorerImpl.RestoreInt64();
	if (T == "double") return oRestorerImpl.RestoreDouble();
	if (T == "string") return oRestorerImpl.RestoreString();
	if (T == "base64") return oRestorerImpl.RestoreBinary();
	if (T == "bool") return oRestorerImpl.RestoreBool();
	if (T == "Value") return oRestorerImpl.RestoreCompound();
	// little spike with Optional
	if (T == "none" || T == "optional") T = "Optional";
	// and with unsigned types
	if (T == "u") T = "Unsigned";
	if (T == "ul") T = "UInt64";
	
	if (!T) return null; // NULL-FIX ('undefined' was here)
	
	var sExec = "var oObj = new "+T+"();";
	try {
		eval(sExec);
	}
	catch (e) {
		LogE("RestorerIF: Cannot create class '"+T+"' from '"+oRestorerImpl.Buffer()+"'");
		return null;
	}
	if (typeof(oObj.Serialize) == "function" && typeof(oObj.Restore) == "function") {
		oObj.Restore(oRestorerImpl);
	} else {
		throw new Error("RestorerIF::restore: Cannot restore object of type '"+T+"' (no .Serialize or .Restore method)");
		oObj = null;
	}
	return oObj;
}

var SerializerIF = Class.create({
initialize: function() { }
});

SerializerIF.serialize = function(oSerializerImpl, oObj, bValueElement) {
	if (!bValueElement) bValueElement = false;
	var T = typeof(oObj);
	// prepare type information
	if (T == "undefined" || oObj === null) {
		T = "null";
	} else if (T == "number") {
		if (isFloat(oObj)) throw new Error("SerializerIF::serialize: You must specify exact type for float numbers! ");
		// default type is Int
		T = "object";
		oObj = int(oObj);
	} else if (T == "object" && oObj instanceof Array) {
		T = "array";
	}
	
	// serialize
	if (T == "undefined" || T == "null") {
		oSerializerImpl.SerializeObject(new Object(), bValueElement);
	} else if (T == "string") {
		oSerializerImpl.SerializeString(oObj);
	} else if (T == "boolean") {
		oSerializerImpl.SerializeBool(oObj);
	} else if (T == "array") {
		oSerializerImpl.SerializeArray(oObj, bValueElement);
	} else if (T == "object") {
		if (typeof(oObj.Serialize) == "function" && typeof(oObj.Restore) == "function") {
			//LogL("Serializing as named object...");
			oObj.Serialize(oSerializerImpl);
		} else {
			//LogL("Serializing as generic object...");
			oSerializerImpl.SerializeObject(oObj, bValueElement);
		}
	} else {
		alert("SerializerIF::serialize: Unhandled type: T="+T+", Obj="+oObj.toString());
		return;
	}
}

