//============= Copyright (c) Ludic GmbH, All rights reserved. ==============
//
// Purpose: Part of the My Behaviour Tree Code
//
//=============================================================================

using System;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;

namespace MyBT {
    public static class ExtensionMethods {
        // Deep clone
        // public static T DeepClone<T>(this T a) where T : ISerializable {
        //     using (MemoryStream stream = new MemoryStream()) {
        //         BinaryFormatter formatter = new BinaryFormatter();
        //         formatter.Serialize(stream, a);
        //         stream.Position = 0;
        //         return (T) formatter.Deserialize(stream);
        //     }
        // }

        // https://stackoverflow.com/questions/129389/how-do-you-do-a-deep-copy-of-an-object-in-net-c-specifically/1213649#1213649
        public static void DeepCopy<T>(T object2Copy, ref T objectCopy) {
            using (var stream = new MemoryStream()) {
                var serializer = new System.Xml.Serialization.XmlSerializer(typeof(T),
                    new Type[]{
                        typeof(Node),
                        typeof(ActionNode),
                        typeof(CompositeNode),
                        typeof(DecoratorNode),
                        typeof(RunTreeNode),
                        typeof(TreeNode),
                        typeof(TaskParameterGroup),
                        typeof(TaskParameter)
                    });

                serializer.Serialize(stream, object2Copy);
                stream.Position = 0;
                objectCopy = (T)serializer.Deserialize(stream);
            }
        }


        #region serialize & deserialize data for script reloading process
        public static byte[] SerializeToByteArray(this object obj) {
            if (obj == null) {
                return null;
            }
            var bf = new BinaryFormatter();
            using (var ms = new MemoryStream()) {
                bf.Serialize(ms, obj);
                return ms.ToArray();
            }
        }

        public static object Deserialize(this byte[] byteArray) {
            if (byteArray == null) {
                return default(object);
            }
            using (var memStream = new MemoryStream()) {
                var binForm = new BinaryFormatter();
                memStream.Write(byteArray, 0, byteArray.Length);
                memStream.Seek(0, SeekOrigin.Begin);
                var obj = binForm.Deserialize(memStream);
                return obj;
            }
        }
        #endregion

        // public static void deepCopy<T>(ref T object2Copy, ref T objectCopy) {
        //     using (var stream = new MemoryStream()) {
        //         Serializer.Serialize(stream, object2Copy);
        //         stream.Position = 0;
        //         objectCopy = Serializer.Deserialize<T>(stream);
        //     }
        // }
    }
}