using ActuBoardAPI;
using System;
using System.Collections.Generic;
using System.IO.Ports;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace ActuBoardConsole
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class ActuBoardApp : Window
    {

        private ActuBoardInterface _abi;
        private int _comport = 0;
        private bool _outputEnabled = true;

        public ActuBoardApp()
        {
            InitializeComponent();


            foreach (String port in SerialPort.GetPortNames())
            {
                drop_com.Items.Add(port);
            }


            _abi = new ActuBoardInterface();
            _abi.OnConnectionChanged += _abi_OnConnectionChanged;
            _abi.OnMessageReceived += _abi_OnMessageReceived;
            _abi.OnStatusUpdate += _abi_OnStatusUpdate;

            drop_com.SelectionChanged += Drop_com_SelectionChanged;
            if (drop_com.Items.Count > 0)
                drop_com.SelectedIndex = 0;

            btn_connect.Click += Btn_connect_Click;

            btn_list.Click += Btn_list_Click;
            btn_send.Click += Btn_send_Click;
            btn_read.Click += Btn_read_Click;
            btn_debug.Click += Btn_debug_Click;
            btn_output.Click += Btn_output_Click;
            btn_send_value.Click += Btn_send_value_Click;

            btn_group_m.Click += Btn_group_m_Click;
            btn_group_n.Click += Btn_group_n_Click;

            btn_test.Click += Btn_test_Click;

        }

        private void Btn_send_value_Click(object sender, RoutedEventArgs e)
        {
            if (_abi.IsConnected() && txt_channel.Text != "")
            {
                int channel = 0;
                Int32.TryParse(txt_channel.Text, out channel);
                int value = 0;
                Int32.TryParse(txt_value.Text, out value);
                if (value > 255 || value < 0)
                    value = 0;
                _abi.SetChannel(channel, value);
            }
        }

        private void Btn_group_n_Click(object sender, RoutedEventArgs e)
        {
            if (_abi.IsConnected())
            {
                int[] channels = { 30, 31, 32 };
                int[] pwm = { 128, 15, 255 };
                _abi.SetChannels(channels, pwm);
            }
        }

        private void Btn_group_m_Click(object sender, RoutedEventArgs e)
        {
            if (_abi.IsConnected())
            {
                int[] channels = { 30, 31, 32 };
                _abi.SetChannels(channels, 128);
            }
        }

        private void _abi_OnStatusUpdate(StatusCode e)
        {
            Dispatcher.BeginInvoke(new Action(delegate ()
            {
                if (e > 0)
                    Console.Beep();

                // error released
                if (e == StatusCode.NoError)
                {
                    el_error.Fill = new SolidColorBrush(Colors.LimeGreen);
                }
                // hardware controller could not interpret command
                else if (e == StatusCode.HardwareCommandError)
                {
                    el_error.Fill = new SolidColorBrush(Colors.Red);
                }
                // selected channel(s) are invalid or out of range
                else if (e == StatusCode.ChannelInvalid)
                {
                    el_error.Fill = new SolidColorBrush(Colors.BlueViolet);
                }
                // pwm value(s) are out of range (0-255)
                else if (e == StatusCode.PwmValueInvalid)
                {
                    el_error.Fill = new SolidColorBrush(Colors.Coral);
                }
                // hardware is not connected
                else if (e == StatusCode.ActuBoardNotConnected)
                {
                    el_error.Fill = new SolidColorBrush(Colors.DarkRed);
                }
                // unknown error ID
                else
                {
                    el_error.Fill = new SolidColorBrush(Colors.Red);
                }
            }));
        }

        private void Btn_test_Click(object sender, RoutedEventArgs e)
        {
            if (_abi.IsConnected())
            {
                _abi.SetChannel("30", "240");
            }
        }

        private void Btn_output_Click(object sender, RoutedEventArgs e)
        {
            if (_abi.IsConnected())
            {
                _abi.EnableOutput(!_outputEnabled);
                _outputEnabled = !_outputEnabled;
                if (_outputEnabled)
                {
                    SetStatusColor(1);
                    btn_output.Content = "disable output";
                }
                else
                {
                    SetStatusColor(3);
                    btn_output.Content = "enable output";
                }
            }
        }

        private void Btn_debug_Click(object sender, RoutedEventArgs e)
        {
            if (_abi.IsConnected())
                _abi.ToggleDebug();
        }

        private void Btn_read_Click(object sender, RoutedEventArgs e)
        {
            if (_abi.IsConnected() && txt_channel.Text != "")
            {
                int channel = 0;
                Int32.TryParse(txt_channel.Text, out channel);
                _abi.GetChannel(channel);
            }
        }

        private void Btn_send_Click(object sender, RoutedEventArgs e)
        {

            if (_abi.IsConnected() && txt_command.Text != "")
            {
                _abi.SendCustomCommand(txt_command.Text);
            }
        }

        private void Btn_list_Click(object sender, RoutedEventArgs e)
        {
            if (_abi.IsConnected())
                _abi.ListDevices();
        }

        private void _abi_OnMessageReceived(string e)
        {
            Console.WriteLine("MSG: " + e);
            Dispatcher.BeginInvoke(new Action(delegate ()
            {
                txt_console.Text += e;
                txt_console.ScrollToEnd();
            }));
        }

        private void _abi_OnConnectionChanged(bool e)
        {
            if (e)
            {
                SetStatusColor(1);
                btn_connect.Content = "Disconnect";
            }
            else
            {
                SetStatusColor(2);
                btn_connect.Content = "Connect";
            }
        }


        private void SetStatusColor(int status)
        {
            // unknown status
            if (status == 0)
                el_status.Fill = new SolidColorBrush(Colors.Black);
            // connected
            else if (status == 1)
                el_status.Fill = new SolidColorBrush(Colors.LimeGreen);
            // disconnected
            else if (status == 2)
                el_status.Fill = new SolidColorBrush(Colors.Red);
            // output disabled
            else if (status == 3)
                el_status.Fill = new SolidColorBrush(Colors.GreenYellow);
        }


        private void Drop_com_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            _comport = ComToInt(drop_com.SelectedItem.ToString());
            _abi.SetComPort(_comport);

        }


        private int ComToInt(String scom)
        {
            Console.WriteLine("COMPORT: " + scom);
            if (scom.StartsWith("COM"))
                return Int32.Parse(scom.Substring(3));
            else
                return 0;
        }

        private void Btn_connect_Click(object sender, RoutedEventArgs e)
        {
            Console.WriteLine("Connecting to " + _comport);
            if (_comport > 0 && !_abi.IsConnected())
                _abi.Connect();
            else if (_abi.IsConnected())
                _abi.Disconnect();
        }

        private void txt_command_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.Key == Key.Enter)
            {
                Console.WriteLine("sender " + sender.ToString());
                btn_send.RaiseEvent(new RoutedEventArgs(Button.ClickEvent));
            }
        }
    }
}
