using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.Runtime.Serialization;

namespace DXGfxLib.Serialization
{
    public sealed class OutDoorSceneSurrogate : ISerializationSurrogate
    {
        /// <summary>
        /// This is called to serialize the Scene.
        /// </summary>
        /// <param name="obj">The scene object that need to be serialized.</param>
        /// <param name="info">where we have to write what we want to be serialized.</param>
        /// <param name="context"></param>
        public void GetObjectData(Object obj, SerializationInfo info, StreamingContext context)
        {
            if (obj == null)
            {
                throw new NullReferenceException("No scene to serialize, this is wrong!");
            }

            OutDoorScene scene = obj as OutDoorScene;

            if (scene == null)
            {
                throw new ArgumentException("The Object passed through obj argument is not an OutDoorScene, this is wrong!");
            }

            info.AddValue("Name", scene.name, typeof(string));
            info.AddValue("Depth", scene.depth, typeof(int));
            info.AddValue("ExtendX", scene.Extents.X, typeof(float));
            info.AddValue("ExtendY", scene.Extents.Y, typeof(float));
            info.AddValue("ExtendZ", scene.Extents.Z, typeof(float));
            info.AddValue("Terrain", scene.SceneTerrain, typeof(Terrain));
            info.AddValue("Sky", scene.SceneSky, typeof(SkyDome));
            info.AddValue("Water", scene.SceneWater, typeof(Water2));
            info.AddValue("SceneContent", scene.sceneContent, typeof(Hashtable));

            if (scene.CurrentAvatar == null)
            {
                info.AddValue("Avatar", "", typeof(string));
            }
            else if (scene.CurrentAvatar.associatedSceneObject == null)
            {
                info.AddValue("Avatar", "", typeof(string));
            }
            else
            {
                info.AddValue("Avatar", scene.CurrentAvatar.associatedSceneObject.name, typeof(string));
            }
        }

        /// <summary>
        /// This is called to deserialize a scene object.
        /// </summary>
        /// <param name="obj">The scene object we need to populate with values.</param>
        /// <param name="info">Serialized information we need to read and push to the scene object.</param>
        /// <param name="context"></param>
        /// <param name="selector"></param>
        /// <returns>null (ignored)</returns>
        public Object SetObjectData(Object obj, SerializationInfo info, StreamingContext context, ISurrogateSelector selector)
        {
            if (obj == null)
            {
                throw new NullReferenceException("No scene to serialize, this is wrong!");
            }

            OutDoorScene scene = obj as OutDoorScene;

            if (scene == null)
            {
                throw new ArgumentException("The Object passed through obj argument is not an OutDoorScene, this is wrong!");
            }

            scene.name = (string)info.GetValue("Name", typeof(string));
            scene.depth = (int)info.GetValue("Depth", typeof(int));
            float X = (float)info.GetValue("ExtendX", typeof(float));
            float Y = (float)info.GetValue("ExtendY", typeof(float));
            float Z = (float)info.GetValue("ExtendZ", typeof(float));
            AABBox aabox = new AABBox(X, Y, Z);
            scene.Initialize(aabox, scene.depth);
            scene.SceneTerrain = (Terrain)info.GetValue("Terrain", typeof(Terrain));
            scene.SceneSky = (SkyDome)info.GetValue("Sky", typeof(SkyDome));
            scene.SceneWater = (Water2)info.GetValue("Water", typeof(Water2));
            scene.sceneContent = (Hashtable)info.GetValue("SceneContent", typeof(Hashtable));
            scene.avatarName = (string)info.GetValue("Avatar", typeof(string));
            
            return null;
        }
    }
}
