using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using System.Runtime.Serialization;

namespace nft.framework {
    class SerializationHelper {
        private static BinaryFormatter failsafeFormatter;
        private static BinaryFormatter defaultFormatter;

        static SerializationHelper() {
            ISurrogateSelector selector = new FailsafeSurrogate();
            failsafeFormatter = new BinaryFormatter(selector, new StreamingContext(StreamingContextStates.All));
            defaultFormatter = new BinaryFormatter();
            defaultFormatter.Context = new StreamingContext(StreamingContextStates.Persistence);
        }

        public static void Save(string filename, object obj) {
            FileInfo file = new FileInfo(filename);
            FileStream stream = file.OpenWrite();
            BinaryFormatter bf = defaultFormatter;
            try {
                bf.Serialize(stream, obj);
            } finally {
                stream.Close();
            }
        }

        public static object Load(string filename, Type type, out bool schemaChange) {
            object obj = null;
            schemaChange = false;
            FileInfo file = new FileInfo(filename);
            if (true /*file.Exists*/) {
                FileStream stream = file.OpenRead();
                BinaryFormatter bf = defaultFormatter;
                try {
                    /*
                    obj = bf.Deserialize(stream);
                } catch (Exception se) {
                    // standad deserialization didn't work so attempt schema migration
                    stream.Seek(0, SeekOrigin.Begin);
                     */
                    bf = failsafeFormatter;
                    obj = bf.Deserialize(stream);
                    schemaChange = true;
                } finally {
                    stream.Close();
                }
            }
            return obj;
        }

        #region old code
        /*
        private static BinaryFormatter CreateFormatter(Type type) {
            ISurrogateSelector selector = new FailsafeSurrogate(type.Assembly);
            return new BinaryFormatter(selector, new StreamingContext(StreamingContextStates.All));
        }

        private static BinaryFormatter CreateFormatter() {
            BinaryFormatter formatter = new BinaryFormatter();
            formatter.Context = new StreamingContext(StreamingContextStates.Persistence);
            return formatter;
        }
        */
        #endregion
    }
}
