using System;
using System.Linq;
using System.Runtime.InteropServices;
using System.Threading;
 
namespace PsTech.Reference
{
    public class Reference
    {
        
        [DllImport("Kernel32")]
        private static extern bool SetConsoleCtrlHandler(ConsoleEventHandler handler, bool add);
 
        private delegate bool ConsoleEventHandler(CtrlType sig);
        static ConsoleEventHandler ConsoleCtrlEventHandler;
 
        public enum CtrlType
        {
            CtrlCEvent = 0,
            CtrlBreakEvent = 1,
            CtrlCloseEvent = 2,
            CtrlLogOffEvent = 5,
            CtrlShutdownEvent = 6,
        }
 
        private static bool ConsoleHandler(CtrlType sig)
        {
            Exithandler((int)sig);
            return true;
        }
 
        public static void PrintMatrix(float[] matrix)
        {
            for (int i = 0; i < 4; i++)
            {
                for (int j = 0; j < 4; j++)
                {
                    Console.Write(matrix[j + i * 4] + "\t");
                }
                Console.WriteLine();
            }
        }
 
        
        static bool Running = true;
 
        
        static int NumberOfSamplesToGrab = 1000;
        static int SamplesGrabbed = 0;
 
        class MyTrackerListener : TrackerListener
        {
            public override void OnTrackerData(TrackerData data, 
ErrorStatus status)
 
            {
                if (SamplesGrabbed++ >= NumberOfSamplesToGrab)
                {
                    Running = false;
                }
 
                
            }
        }
 
        static void Exithandler(int sig)
        {
            Tracker.Shutdown();
            Running = false;
        }
        static int Main(string[] args)
        {
            
            ConsoleCtrlEventHandler += new ConsoleEventHandler(ConsoleHandler);
            SetConsoleCtrlHandler(ConsoleCtrlEventHandler, true);
 
            
            
            try
            {
                
                Tracker tracker = new Tracker();
 
                
                Console.Write("Running PST Server version " + tracker.GetVersionInfo() + "\n");
 
                
                TrackerListener listener = new MyTrackerListener();
 
                
                tracker.AddTrackerListener(ref listener);
 
                
                tracker.StartTracker();
 
                
                Console.Write("System check: " + tracker.Systemcheck() + "\n\n");
 
                
                tracker.SetFramerate(30);
 
                
                
                Console.Write("Frame rate set to " + tracker.GetFramerate() + "\n\n");
                Console.Write("*******************\n\n");
 
                
                Console.Write("Current reference system transformation matrix:\n");
                PrintMatrix(tracker.GetReference());
 
                Console.Write("\n\n*******************\n\n");
 
                
                
                
                
                float[] reference = {  -1.0f,  0.0f,  0.0f,  0.1f,
                                        0.0f,  0.0f,  1.0f, -0.5f,
                                        0.0f,  1.0f,  0.0f,  0.5f,
                                        0.0f,  0.0f,  0.0f,  1.0f };
                tracker.SetReference(reference);
                Console.Write("New reference system transformation matrix:\n");
                PrintMatrix(tracker.GetReference());
 
                
                if (tracker.GetReference().SequenceEqual(reference))
                {
                    Console.Write("Reference set correctly!\n");
                }
                else
                {
                    Console.Write("Reference not set correctly!\n");
                }
                Console.Write("\n\n*******************\n\n");
 
                
                float[] nonOrthoNormalReference = { -1.0f,  1.0f,  0.0f,  0.1f,
                                                    0.0f,  0.0f, -1.0f, -0.5f,
                                                    0.0f, -1.0f,  0.0f,  0.5f,
                                                    0.0f,  0.0f,  0.0f,  1.0f };
 
                try
                {
                    tracker.SetReference(nonOrthoNormalReference);
                    Console.Write("Reference input incorrectly applied!");
                }
                {
                    
                    Console.Write("Reference input correctly ignored: " + e.Message + "\n");
                }
                Console.Write("New reference system after applying non-orthonormal transformation:\n");
                PrintMatrix(tracker.GetReference());
 
                Console.Write("\n\n*******************\n\n");
 
                
                
                float[] relativeReference = {   0.0f, -1.0f,  0.0f,  0.5f,
                                                1.0f,  0.0f,  0.0f,  0.4f,
                                                0.0f,  0.0f,  1.0f,  0.0f,
                                                0.0f,  0.0f,  0.0f,  1.0f };
                tracker.SetReference(relativeReference, true);
                Console.Write("New reference system after applying relative transformation:\n");
                PrintMatrix(tracker.GetReference());
 
                Console.Write("\n\n*******************\n\n");
 
                
                
                tracker.SetDefaultReference();
                Console.Write("Reset default reference system:\n");
                PrintMatrix(tracker.GetReference());
 
                
                while (Running)
                {
                    Thread.Sleep(100);
                }
            }
            {
                
                Console.Write(e + "\n");
            }
            finally
            {
                
                Tracker.Shutdown();
            }
 
            
            Console.Write("Press enter to continue...\n");
            Console.Read();
 
            return 0;
        }
    }
}