using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

using System.IO;
using System.IO.MemoryMappedFiles;
using System.Threading;
using System.Runtime.Serialization.Formatters.Binary;
using System.Reflection;

namespace Memory_client
{
    public partial class Form1 : Form
    {
        [Serializable]
        public class WindDirectionData
        {
            public string[,] dir_values;
        }

        [Serializable]
        public class WindSpeedData
        {
            public string[,] spd_values;
        }
        sealed class AllowAllAssemblyVersionsDeserializationBinder : System.Runtime.Serialization.SerializationBinder
        {
            public override Type BindToType(string assemblyName, string typeName)
            {
                Type typeToDeserialize = null;

                String currentAssembly = Assembly.GetExecutingAssembly().FullName;

                // In this case we are always using the current assembly
                assemblyName = currentAssembly;

                // Get the type using the typeName and assemblyName
                typeToDeserialize = Type.GetType(String.Format("{0}, {1}",
                    typeName, assemblyName));

                return typeToDeserialize;
            }
        }


        public Form1()
        {
            InitializeComponent();
            
        }
        MemoryMappedViewAccessor mmfReader;
        MemoryMappedFile mmf2;

        private void Button1_Click(object sender, EventArgs e)
        {

            WindSpeedData wsd = ReadObjectFromMMF("windSpeedData") as WindSpeedData;
            Console.WriteLine("wsd:" + wsd.spd_values[0, 1]);

            WindDirectionData wdd = ReadObjectFromMMF("windDirectionData") as WindDirectionData;
            Console.WriteLine("wdd:" + wdd.dir_values[0, 1]);
        }

        public object ReadObjectFromMMF(string name)
        {
            // Get a handle to an existing memory mapped file
            Console.WriteLine(name);
            using (mmf2 = MemoryMappedFile.OpenExisting("Global\\" + name, MemoryMappedFileRights.Read))
            {

                using (mmfReader = mmf2.CreateViewAccessor(0, 0, MemoryMappedFileAccess.Read))
                {
                    Mutex mutex = Mutex.OpenExisting(@"Global\MyMutex");
                    mutex.WaitOne();
                    byte[] buffer = new byte[mmfReader.Capacity];
                    mmfReader.ReadArray<byte>(0, buffer, 0, buffer.Length);
                    mutex.ReleaseMutex();

                    // Convert the buffer to a .NET object
                    return ByteArrayToObject(buffer);
                }
            }

        }

        public object ByteArrayToObject(byte[] buffer)
        {
            BinaryFormatter binaryFormatter = new BinaryFormatter(); // Create new BinaryFormatter
            MemoryStream memoryStream = new MemoryStream(buffer);    // Convert buffer to memorystream
            binaryFormatter.Binder = new AllowAllAssemblyVersionsDeserializationBinder();

            return binaryFormatter.Deserialize(memoryStream);        // Deserialize stream to an object
        }


    }
}
