using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.Serialization;
using System.IO;
using Microsoft.DirectX;
using Microsoft.DirectX.Direct3D;
using Microsoft.Samples.DirectX.UtilityToolkit;

namespace DXGfxLib.Serialization
{
    public class SceneObjectSurrogate : 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 object to serialize, this is wrong!");
            }

            SceneObject sobj = obj as SceneObject;

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

            info.AddValue("Name", sobj.name, typeof(string));
            info.AddValue("Type", sobj.GetType().ToString(), typeof(string));
            info.AddValue("Filename", sobj.fileName, typeof(string));

            //info.AddValue("X", sobj.X, typeof(float));
            //info.AddValue("Y", sobj.Y, typeof(float));
            //info.AddValue("Z", sobj.Z, typeof(float));
            //info.AddValue("Yaw", sobj.Yaw, typeof(float));
            //info.AddValue("Pitch", sobj.Pitch, typeof(float));
            //info.AddValue("Roll", sobj.Roll, typeof(float));

            info.AddValue("m11", sobj.worldMat.M11, typeof(float));
            info.AddValue("m12", sobj.worldMat.M12, typeof(float));
            info.AddValue("m13", sobj.worldMat.M13, typeof(float));
            info.AddValue("m14", sobj.worldMat.M14, typeof(float));

            info.AddValue("m21", sobj.worldMat.M21, typeof(float));
            info.AddValue("m22", sobj.worldMat.M22, typeof(float));
            info.AddValue("m23", sobj.worldMat.M23, typeof(float));
            info.AddValue("m24", sobj.worldMat.M24, typeof(float));

            info.AddValue("m31", sobj.worldMat.M31, typeof(float));
            info.AddValue("m32", sobj.worldMat.M32, typeof(float));
            info.AddValue("m33", sobj.worldMat.M33, typeof(float));
            info.AddValue("m34", sobj.worldMat.M34, typeof(float));

            info.AddValue("m41", sobj.worldMat.M41, typeof(float));
            info.AddValue("m42", sobj.worldMat.M42, typeof(float));
            info.AddValue("m43", sobj.worldMat.M43, typeof(float));
            info.AddValue("m44", sobj.worldMat.M44, typeof(float));


            if (sobj.OurScript != null)
            {
                info.AddValue("VarSrc", sobj.OurScript.VarSrc);
                info.AddValue("CodeSrc", sobj.OurScript.CodeSrc);
                info.AddValue("OnClickSrc", sobj.OurScript.ClickCodeSrc);
                info.AddValue("OnCollSrc", sobj.OurScript.CollisionCodeSrc);
            }
            else
            {
                info.AddValue("VarSrc", "");
                info.AddValue("CodeSrc", "");
                info.AddValue("OnClickSrc", "");
                info.AddValue("OnCollSrc", "");
            }


        }

        /// <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 object to serialize, this is wrong!");
            }

            SceneObject sobj = obj as SceneObject;

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

            sobj.name = (string)info.GetValue("Name",typeof(string));
            sobj.Initialize();
            string type = (string)info.GetValue("Type", typeof(string));
            sobj.fileName = (string)info.GetValue("Filename", typeof(string));

            if (!File.Exists(sobj.fileName))
            {
                // Check if in Media subfolder.
                if (!File.Exists(DXGfxManager.GetGlobalInstance().mediaFolderPath + "\\" + sobj.fileName))
                {
                    throw new Exception("File : " + sobj.fileName + " does not exist we are going to have a problem. Please check the Media folder associated with your scene is in the same folder as the scene xml file.");
                }
                
            }

            //float X = (float)info.GetValue("X", typeof(float));
            //float Y = (float)info.GetValue("Y", typeof(float));
            //float Z = (float)info.GetValue("Z", typeof(float));
            //float Yaw = (float)info.GetValue("Yaw", typeof(float));
            //float Pitch = (float)info.GetValue("Pitch", typeof(float));
            //float Roll = (float)info.GetValue("Roll", typeof(float));

            Matrix world;

            world.M11 = (float)info.GetValue("m11", typeof(float));
            world.M12 = (float)info.GetValue("m12", typeof(float));
            world.M13 = (float)info.GetValue("m13", typeof(float));
            world.M14 = (float)info.GetValue("m14", typeof(float));

            world.M21 = (float)info.GetValue("m21", typeof(float));
            world.M22 = (float)info.GetValue("m22", typeof(float));
            world.M23 = (float)info.GetValue("m23", typeof(float));
            world.M24 = (float)info.GetValue("m24", typeof(float));

            world.M31 = (float)info.GetValue("m31", typeof(float));
            world.M32 = (float)info.GetValue("m32", typeof(float));
            world.M33 = (float)info.GetValue("m33", typeof(float));
            world.M34 = (float)info.GetValue("m34", typeof(float));

            world.M41 = (float)info.GetValue("m41", typeof(float));
            world.M42 = (float)info.GetValue("m42", typeof(float));
            world.M43 = (float)info.GetValue("m43", typeof(float));
            world.M44 = (float)info.GetValue("m44", typeof(float));
            //Matrix world = Matrix.Multiply(Matrix.RotationYawPitchRoll(Yaw, Pitch, Roll), Matrix.Translation(X, Y, Z));

            sobj.worldMat = world;

            Script theScript = new Script();
            theScript.UpdateVarSrc((string)info.GetValue("VarSrc", typeof(string)));
            theScript.UpdateCodeSrc((string)info.GetValue("CodeSrc", typeof(string)));
            theScript.UpdateClickCodeSrc((string)info.GetValue("OnClickSrc", typeof(string)));
            theScript.UpdateCollisionCodeSrc((string)info.GetValue("OnCollSrc", typeof(string)));

            sobj.script = theScript;

            return null;
        }

    }
}
