using System;

namespace MiComv2022_MicroMac
{
    internal class HMS_MiCom2022_MicroMAC_XEtat
    {

        static void Main()
        {
            // the MiCom_v2022.dll assembly is referenced in the  project:
            // so the next line is valid and 'myCom' will be the instance of the MiCom_v2022 type
            Midi_Ingenierie.MiComm_2022 myCom = new Midi_Ingenierie.MiComm_2022();

            int status;
            string ComName = null;

            string[] arg = Environment.GetCommandLineArgs();

            Console.BackgroundColor = ConsoleColor.White;
            Console.ForegroundColor = ConsoleColor.Black;

            Title("Demo_MiCom2022_MicroMAC_XEtat.exe ==> how to use MICom2022 for MICROMAC17, detail on the X_Etat property");
            Display("Usage : HMS_MiCom2022_MicroMac_XEtat.exe  \"ComName\"  ");
            Display();
            Display("myCom is the instance of MiCom_v2022 type , from C# new Midi_Ingenierie.MiComm_2022()");
            Display();
            Display("Check version and copyright : ");
            Output("MiComm_2022.Identity => ", Midi_Ingenierie.MiComm_2022.Identity );
            Display();

            if (arg.Length > 1)
            {
                Display(arg[1] + " founded in argument list : used as ComName");
                ComName = arg[1];
            }
            else
            {
                Console.Write("no ComName ref in command line argument : ");
                Console.Write("input a ComName >"); ComName = Console.ReadLine();
            }
            

            Display("myCom.Open  , select DRIVER , PORTCOM , and BAUDRATE   all as string (C#) ");
            status = myCom.Open("MICROMAC17", ComName, "38400");
            Output("myCom.Open('MICROMAC17', '"+ComName +"', '38400') => ", "myCom.Status="+status.ToString("X4") );

            Display();
            Display("myCom.Send  , send a command / requete to the MICROMAC17 driver , adress 00");
            status = myCom.Send("00RV");
            Output("myCom.Send(\"00RV\") => ", "myCom.Status (or Cr) =" + status.ToString("X4"));

            
            if (status != 0x0001)
            {
                // something failed , so this demo program is terminate
                Warning();
                Quit();
                return;  
            }
            
            Display("Cr=0x0001 , b0=1 : a reponse from the MICROMAC17 exist in myCom.Reponse");
            Output("myCom.Reponse => ", myCom.Reponse);

            
            ConsoleKey key_ = Ask("Start motor, only if motor is FREE  [Y/N] ?");
            if (key_ != ConsoleKey.Y)
            {
                // user choice : quit this demo program
                return;
            }

            Display();

            // note : the 'HALT' command with NO ADRESS  = GLOBAL COMMAND
            myCom.Send("HALT");
            // note : this setting command allows to fix the module absolute position counter to 0
            myCom.Send("00#POSITION = 0");

            Display("The start command : ");
            myCom.Send("00MOVE_ON +10000");
            // note : use of the MiCom Status and XEtat properties
            Output("myCom.Send(\"00MOVE_ON +10000\") => ", "myCom.Status= " + myCom.Status.ToString("X4")  );

            Display();

            // note : the next MOVE_ON command will be on error if the motor is still in movement 
            Display("Another MOVE_ON command only when the current movement will be completed  (myCom.X_Etat.b1 = 0)");
            Display("the X_Etat code is embebed in the protocol trame. ");
            // note : the module µMAC is in movement , so the curent X_Etat must be egal to 0x83
            myCom.Send("00REA #POS");
            int XEtat = myCom.X_Etat; // this is the ACTUAL X_ETAT
            Output("myCom.X_Etat = " , myCom.X_Etat.ToString("X2"));


            while (XEtat == 0x83)
            {
                //warnig : insert a delay between the start CMDE and the first read of X_Etat
                System.Threading.Thread.Sleep(200);
                myCom.Send("00REA #POS");
                XEtat = myCom.X_Etat;
                Output("myCom.Send(\"00REA #POS\") => ","myCom.Reponse: ["+ myCom.Reponse + "]   , myCom.X_Etat =" + XEtat.ToString("X2"));
            }
            Display("the last X_Etat.b1=0  (0x81) , so the last movement is completed");
                   
            myCom.Send("00MOVE_ON -3000");
            Output("myCom.Send(\"00MOVE_ON -3000\") => ", " myCom.Status= " + myCom.Status.ToString("X4"));

            Display();
            Display("Wait for the end of the last MOVE_ON command : check X_Etat");
            XEtat = 0x83;
            while (XEtat == 0x83)
            {
                System.Threading.Thread.Sleep(200);
                myCom.Send("00REA #POS");
                XEtat = myCom.X_Etat;
                Output("myCom.Send(\"00REA #POS\") => ", "myCom.Reponse: [" + myCom.Reponse + "]   , myCom.X_Etat =" + XEtat.ToString("X2"));
            }

            Display("the last MOVE_ON is ended :");
       


            Display("\nPOWER OFF in 2s");
            System.Threading.Thread.Sleep(2000);
            Display();


            // note : a command with NO ADRESS  = GLOBAL COMMAND
            myCom.Send("POWER OFF");
            Output("myCom.Send(\"POWER OFF\") => ", "myCom.X_Etat =" + myCom.X_Etat.ToString("X2"));
            Display("!! the X_Etat is set before the final execution of the command ");
            Display("so , with the POWER OFF command , the X_Etat.b0 (power) is still '1'");
            Display("another command will return the X_Etat.b0 set to 0  which is the POWER OFF command reaction");

            myCom.Send("00REA #POS");
            Output("myCom.Send(\"00REA #POS\") => ", "myCom.Reponse: [" + myCom.Reponse + "]   , myCom.X_Etat =" + myCom.X_Etat.ToString("X2"));


            Quit();
        }




        private static void Title(string message)
        {
            Console.Clear();
            ConsoleColor currentForeground = Console.ForegroundColor;
            Console.ForegroundColor = ConsoleColor.DarkRed;
            Console.WriteLine(message);           
            Console.ForegroundColor = currentForeground;
        }

        private static void Display(string Texte = "")
        {
            if (string.IsNullOrEmpty(Texte))
            {
                Console.WriteLine();
            }
            else
            {
                ConsoleColor currentForeground = Console.ForegroundColor;
                Console.ForegroundColor = ConsoleColor.Black;
                Console.WriteLine(Texte);
                Console.ForegroundColor = currentForeground;
            }
        }

        private static void Output(string Texte_1, string Texte_2)
        {
            ConsoleColor currentForeground = Console.ForegroundColor;
            Console.ForegroundColor = ConsoleColor.DarkBlue; Console.Write(Texte_1);
            Console.ForegroundColor = ConsoleColor.DarkGreen; Console.WriteLine(Texte_2);
            Console.ForegroundColor = currentForeground;

        }

        private static void Warning()
        {
            ConsoleColor currentForeground = Console.ForegroundColor;
            Console.WriteLine();
            Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine("the Cr is a bad one : Check the line , see MiComv2022 doc");
            Console.WriteLine();
            Console.ForegroundColor = currentForeground;
        }

        private static ConsoleKey Ask(string Texte)
        {
            ConsoleColor currentForeground = Console.ForegroundColor;
            Console.ForegroundColor = ConsoleColor.Magenta;
            Console.WriteLine();
            Console.Write(Texte);
            Console.ForegroundColor = currentForeground;
            return Console.ReadKey().Key;
        }

        private static void Quit()
        {
            Console.WriteLine();
            Console.WriteLine();
            Console.Write("[ESC] = Quit the program"); Console.ReadKey();
        }


    }
}
