using System;
namespace MiComv2022_MicroMac
{
    internal class HMS_MiCom2022_MicroMac
    {   
        static void Main()
        {
            const int __FAIL_ERROR__ = 0x8000;

            // 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;

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

            Title("HMS_MiCom2022_MicroMac.exe   ==> how to use MiCom2022 for MICROMAC17 brushless digital axis");
            Display("Usage : HMS_MiCom2022_MicroMac.exe  \"ComName\"  ");

            Display("myCom is the instance of MiCom_v2022 type , from C# new Midi_Ingenierie.MiComm_2022() \n");
            
            Display("Check version and copyright : ");
            Output("MiComm_2022.Identity := ",Midi_Ingenierie.MiComm_2022.Identity+"\n\n");

            // looking for a ComName ref in the command line arguments
            string[] arg = Environment.GetCommandLineArgs();
            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("Open  , select DRIVER , PortCOM , and baudrate   all as string (C#) ");

            status = myCom.Open("MICROMAC17", ComName, "38400");
            Output("myCom.Open(\"MICROMAC17\", \"COMxx\", \"38400\")  => " , status.ToString("X4") + "\n\n");
           
            Display("Send  , send a command / requete to the MICROMAC17 driver , adress 00");
            status = myCom.Send("00RV");
            Output("myCom.Send(\"00RV\")  => ",  status.ToString("X4") +"\n");
            if (status == 0x0001)
            {
                Display("Cr=0x0001 ==> a reponse from the MICROMAC17 exist : myCom.Reponse");
                Output("myCom.Reponse = ", myCom.Reponse + "\n");
            }
            if (status != 0x0001)
            {
                Warning();  
            }
            else
            {
                ConsoleKey key_ = Ask("Start motor, only if motor is FREE  [Y/N] ?");
                if (key_ == ConsoleKey.Y)
                {
                    // note : the 'HALT' command with NO ADRESS  = GLOBAL COMMAND
                    myCom.Send("HALT");myCom.Send("00#POSITION = 0");

                    Display("\nThe start command : ");
                    myCom.Send("00MOVE_ON +10000");
                    // note : use of the property Status
                    Output("myCom.Send(\"00MOVE_ON +10000\") ", " Status= " + myCom.Status.ToString("X4") +"\n\n");

                    Display("Get POSITIONs:  (5 cmdes 00REA #POSITION )");
                    for (int i = 0; i < 5; i++)
                    {   // note : the REA COMMANDs must have an adress
                        myCom.Send("00REA #POSITION");
                        Output("myCom.Send(\"00REA #POSITION\")  :", myCom.Reponse +"\n");
                    }
                    Display();

                    // note : the next MOVE_ON command will be on error 
                    Display("Another MOVE_ON command : ");
                    myCom.Send("00MOVE_ON -5000");status = myCom.Status;
                    Output("myCom.Send(\"00MOVE_ON -5000\") ", " myCom.Status= " + status.ToString("X4") + "\n");
                    if (status > __FAIL_ERROR__)
                    {
                        Display("myCom.Status is > 0x8000 ==> an error occured on the last command !!");
                        Display("0x8800: b15 (Fail/Error) = 1  and b11 (Recept Nack or Failed)  = 1 ");
                        Display("Recept Nack or Failed error is set , use the property DetailCr for error description");
                        Output("myCom.DetailCr  = ", myCom.DetailCr.ToString("X4") +"\n");
                        Display("0x0020: b05 (Error Cmde ) = 1 ");
                        Display("doc umac_v6_um_fr.pdf, p29, MOVE_ON command: command reject error if the motor is already in movement !!");
                        Display("");

                        // note: the status we have to check is the MOVE_ON ' one , not an other'one command                       
                        while (status  != 0x0000)
                        {
                            Display("wait 200ms and try again :");
                            System.Threading.Thread.Sleep(200);
                            myCom.Send("00MOVE_ON -5000");status = myCom.Status;

                            //note: POS is the condensed form of POSITION
                            myCom.Send("00REA #POS");
                            //note : if status = 0x0000 ,the MOVE_ON cmde is passed , so the MVT is start and the POS will be less than 10000
                            Output("myCom.Send(\"00MOVE_ON -5000 then 00REA #POS\") ", " Status= " + status .ToString("X4") +"   "+ myCom.Reponse + "\n");                        
                        }
                        Display();
                        Display("the MICROMAC17 is running from position = 10000 to 5000\n");
                        Display("Check position  : REA #POSITION , extract µMAC position , until position < 5010");
                        bool done = false; 
                        int Position = 0;
                        while (! done)
                        { 
                            // note : the REA commands must have an module adress
                            myCom.Send("00REA #POS");
                            if (ExtractPosition(myCom.Reponse, ref Position))
                            {
                                Output("myCom.Send(\"00REA #POS\") ",  myCom.Reponse);Console .WriteLine(" Position =" + Position.ToString());
                                if (Position < 5010)
                                {
                                    done = true;
                                }
                            }
                            System.Threading.Thread.Sleep(80);
                        }
                    }
                    Display("\n\nPower OFF = no more motor current");
                    // note : a command with NO ADRESS  = GLOBAL COMMAND
                    myCom.Send("POWER OFF");
                    Output("myCom.Send(\"POWER OFF\")", "\n");
                }
            }
            Quit();
        }


        private static bool ExtractPosition(string trame_,ref int pos)
        {
            //trame_  = "00#POS= position"
            //extraction de la position
            //
            pos    = 1000;
            int Pos_Egal = trame_.IndexOf('=');
            if (Pos_Egal == -1) // anomalie si absence du '='
            {
                return false;
            }

            //isole la valeur dans la trame 
            string working = trame_.Substring(Pos_Egal + 1);
            return (int.TryParse(working, out pos));
        }


        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 = "") => Console.WriteLine(Texte);

        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.Write(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.Write("\n[ESC] = All is done ,quit the program"); 
            Console.ReadKey();
        }



    }
}
