using System;
using System.Threading;
using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;

namespace WIFI
{
    // Some generic shell commands
    public static class ShellCommands
    {
        static AutoResetEvent Arrived = new AutoResetEvent(false);
        static CPF.Bellows SqueezeBox = new CPF.Bellows(10.0, 1000);

        public static void There(double position)
        {
            Debug.Print("At Desired position " + position.ToString());
            Arrived.Set();
        }

        // Binds to the Shell Core
        public static void Bind(ShellCore Shell)
        {
            Shell.OnCommandReceived += new ShellCore.CommandReceived(Shell_OnCommandReceived);
            Shell.OnConnected += new ShellCore.ConnectionStateChange(Shell_OnConnected);
            SqueezeBox.AtDesiredPosition += new CPF.Bellows.Position(ShellCommands.There);
        }

        // Unbinds from the Shell Core
        public static void Unbind(ShellCore Shell)
        {
            Shell.OnConnected -= new ShellCore.ConnectionStateChange(Shell_OnConnected);
            Shell.OnCommandReceived -= new ShellCore.CommandReceived(Shell_OnCommandReceived);
            SqueezeBox.AtDesiredPosition -= new CPF.Bellows.Position(ShellCommands.There);
        }

        // Triggered when the connection has been made
        private static void Shell_OnConnected(ShellCore Shell, string RemoteAddress, DateTime Time)
        {
            Shell.TelnetServer.Color(TelnetServer.Colors.White, TelnetServer.Colors.Black);
            Shell.TelnetServer.ClearScreen();
            _SendMotd(Shell.TelnetServer);
        }

        // Sends the MOTD
        private static void _SendMotd(TelnetServer Server)
        {
            Server.Color(TelnetServer.Colors.HighIntensityWhite);
            Server.Print("Welcome to the Coastal Profiler Telnet Server, Connected to: " + Server.RemoteAddress);
            Server.Print("Copyright MBARI @ 2013, All rights reserved.");
            Server.Print("Type HELP to see a list of all supported commands");
            Server.Print("");
            Server.Color(TelnetServer.Colors.White);
        }

        // Triggered when a command has been given
        private static void Shell_OnCommandReceived(ShellCore Shell, string[] Arguments, ref bool SuspressError, DateTime Time)
        {
            switch (Arguments[0].ToUpper())
            {
                case "CLS":
                    Shell.TelnetServer.ClearScreen();
                    SuspressError = true;
                    break;
                case "MOTD":
                    _SendMotd(Shell.TelnetServer);
                    SuspressError = true;
                    break;
                case "ECHO":
                    Shell.TelnetServer.Print(Shell.LastCommandline.Substring(5));
                    SuspressError = true;
                    break;
                case "REBOOT":
                    Shell.TelnetServer.Print("Rebooting...");
                    Thread.Sleep(100);
                    Shell.TelnetServer.Close();
                    PowerState.RebootDevice(false);
                    SuspressError = true;
                    break;
                case "QUIT":
                    Shell.TelnetServer.Print("Bye!");
                    Thread.Sleep(100);
                    Shell.TelnetServer.Close();
                    SuspressError = true;
                    break;
                case "INFO":
                    Shell.TelnetServer.Print("Manufacturer: " + SystemInfo.OEMString);
                    Shell.TelnetServer.Print("Firmware version: " + SystemInfo.Version.ToString());
                    Shell.TelnetServer.Print("Memory available: " + Tools.MetricPrefix(Debug.GC(false), true) + "B");
                    if (PowerState.Uptime.Days == 0)
                        Shell.TelnetServer.Print("Uptime: " + PowerState.Uptime.ToString());
                    else
                        Shell.TelnetServer.Print("Uptime: " + PowerState.Uptime.Days.ToString() + " days, " + PowerState.Uptime.ToString());
                    Shell.TelnetServer.Print("Hardware provider: " + Tools.HardwareProvider);
                    Shell.TelnetServer.Print("System clock: " + Tools.MetricPrefix(Cpu.SystemClock) + "hz");
                    Shell.TelnetServer.Print("Endianness: " + (SystemInfo.IsBigEndian ? "Big Endian" : "Little Endian"));
                    Shell.TelnetServer.Print("Debugger: " + (System.Diagnostics.Debugger.IsAttached ? "attached" : "not attached"));
                    SuspressError = true;
                    break;
                case "POSITION":
                    try
                    {
                        double position = double.Parse(Arguments[1]);
                        Shell.TelnetServer.Print("Moving to position: " + position.ToString() + " mm");
                        SqueezeBox.MoveToPosition(position, (position - 0.25), (position + 0.25), 10000);
                        Arrived.WaitOne();
                    }
                    finally
                    {
                        //SqueezeBox.Stop();
                    }
                    SuspressError = true;
                    break;
                case "VER":
                    System.Reflection.Assembly[] Assemblies = AppDomain.CurrentDomain.GetAssemblies();
                    for (int i = 0; i < Assemblies.Length; ++i)
                        Shell.TelnetServer.Print(Assemblies[i].FullName);
                    SuspressError = true;
                    break;
                case "HELP":
                    bool PageFound = false;
                    if (Arguments.Length == 1) PageFound = DoHelp(Shell.TelnetServer, "");
                    else PageFound = DoHelp(Shell.TelnetServer, Arguments[1].ToUpper());
                    if (PageFound) SuspressError = true;
                    break;
            }
        }

        // Shows a specific help page
        private static bool DoHelp(TelnetServer Server, string Page)
        {
            switch (Page)
            {
                case "":
                    Server.Print("CLS                                Clears the screen");
                    Server.Print("ECHO [TEXT]                        Prints out the text");
                    Server.Print("MOTD                               Shows the message of the day");
                    Server.Print("QUIT                               Closes the connection");
                    Server.Print("POSITION NUM                       Moves the bellows to NUM mm");                         
                    Server.Print("VER                                Shows the version of all loaded assemblies");
                    Server.Print("INFO                               Shows some system info");
                    Server.Print("REBOOT                             Restarts the device");
                    return true;
                case "VER":
                    Server.Print("VER                                Shows the version of all loaded assemblies");
                    return true;
                case "POSITION":
                    Server.Print("POSITION NUM                       Moves the bellows to NUM mm");     
                    return true;
                case "REBOOT":
                    Server.Print("REBOOT                             Restarts the device");
                    return true;
                case "MOTD":
                    Server.Print("MOTD                               Shows the message of the day");
                    return true;
                case "INFO":
                    Server.Print("INFO                               Shows some system info");
                    return true;
                case "CLS":
                    Server.Print("CLS                                Clears the screen");
                    return true;
                case "ECHO":
                    Server.Print("ECHO [TEXT]                        Prints out the text");
                    Server.Print("- [TEXT]  Text to print out");
                    return true;
                case "QUIT":
                    Server.Print("QUIT                               Closes the connection");
                    return true;
                default:
                    return false;
            }
        }
    }
}
