using System.Text;
using System.Windows;
using System.IO;
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;
using System.IO.Ports;
using System.ComponentModel;
using static K11_CNC.MainWindow;
using K11_CNC.ViewModel;
using System.Diagnostics;

namespace K11_CNC
{
    public class MCommand : INotifyPropertyChanged
    {
        public MCommand(char qualif)
        {
            qualifier = qualif;
        }
        public char qualifier { get; set; }
        public Direction dir { get; set; }
        public int Speed { get; set; }
        public int Step { get; set; }
        public int DALIadr { get; set; }
        public int DALIval { get; set; }

        public event PropertyChangedEventHandler? PropertyChanged;
        public string cmd()
        {
            return (qualifier.ToString() + Step.ToString("D6") + "S" + Speed.ToString("D4") + "D" + DALIadr.ToString("D2") + "L" + DALIval.ToString("D3"));
        }
    }
    public class ValidationRuleInt
    {
        public int lower { get; set; }
        public int upper { get; set; }
        public ValidationRuleInt(int lower, int upper)
        {
            this.lower = lower;
            this.upper = upper;
        }
    }
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        MainViewModel vm;
        public enum Direction
        {
            forward,
            back
        }

        SerialPort myCOM = new SerialPort();
        String? newReceived = null;

        string[] Ports = SerialPort.GetPortNames();
        //bool checkd? = false;
        public Motor? myM = null;

        public MainWindow()
        {
            InitializeComponent();
            vm = (MainViewModel)this.TryFindResource("vm");
            if (vm != null)
            {
                this.CommandBindings.Add(vm.NewCommandBinding);
                this.CommandBindings.Add(vm.DeleteCommandBinding);
                this.CommandBindings.Add(vm.SaveCommandBinding);
                this.CommandBindings.Add(vm.UndoCommandBinding);
            }
            this.Closing += MainWindow_Closing;
            vm.ConfirmDeleting += vm_ConfirmDeleting;
            DataContext = vm;
            //this.DataContext = this;
            //Binding binding = new Binding("Content");
            //binding.Source = Motor;

            //myCOM.PortName = Ports[0];
            myCOM.BaudRate = 115200;
            myCOM.DataBits = 8;
            myCOM.Parity = Parity.None;
            myCOM.StopBits = StopBits.One;
            //myCOM.Open();
            tbxDALIadr.Tag = new ValidationRuleInt(0, 63);
            tbxDALIval.Tag = new ValidationRuleInt(0, 254);
            tbxSpeed.Tag = new ValidationRuleInt(0, 1000);
            tbxSteps.Tag = new ValidationRuleInt(-8000, 8000);
            //Command myCmd = new();
            foreach (string s in Ports)
            {
                cbxCOMport.Items.Add(s);
            }
            if (cbxCOMport.Items.Count == 0) btnPortOpen.IsEnabled = false;
            myM = new Motor();
            stpMotorData.DataContext = myM;

        }
        private void vm_ConfirmDeleting(object sender, CancelEventArgs e)
        {
            string message = "Wollen Sie wirklich löschen?";
            string caption = "MVVM_Sample";
            if (MessageBoxResult.Yes == MessageBox.Show(message, caption, MessageBoxButton.YesNo, MessageBoxImage.Question, MessageBoxResult.No))
            {
                e.Cancel = false;
                return;
            }
            e.Cancel = true;
        }

        void MainWindow_Closing(object sender, CancelEventArgs e)
        {
            vm.CancelViewClosing();
        }

        private void btnStop_Click(object sender, RoutedEventArgs e)
        {
            if (myCOM.IsOpen) myCOM.Write("c\r\n");
        }

        private void btnLeft_Click(object sender, RoutedEventArgs e)
        {
            if ((bool)rbnCruise.IsChecked!)
            {
                string cmdline = BuildCmd('Y');
                if (myCOM.IsOpen) myCOM.Write(cmdline);
            }
        }
        private void btnRight_Click(object sender, RoutedEventArgs e)
        {
            if ((bool)rbnCruise.IsChecked!)
            {
                string cmdline = BuildCmd('y');
                if (myCOM.IsOpen) myCOM.Write(cmdline);
            }
        }
        private void btnUp_Click(object sender, RoutedEventArgs e)
        {
            if ((bool)rbnCruise.IsChecked!)
            {
                string cmdline = BuildCmd('X');
                if (myCOM.IsOpen) myCOM.Write(cmdline);
            }
        }
        private void btnDown_Click(object sender, RoutedEventArgs e)
        {
            string cmdline = BuildCmd('x');
            if (myCOM.IsOpen) myCOM.Write(cmdline);
        }
        private string BuildCmd(char quali)
        {
            MCommand newcmd = new MCommand(quali);
            int steps = InRange(tbxSteps);
            if (steps >= 0) newcmd.Step = steps;
            int speed = InRange(tbxSpeed);
            if (speed >= 0) newcmd.Speed = speed;
            int dalia = InRange(tbxDALIadr);
            if (dalia >= 0) newcmd.DALIadr = dalia;
            int daliv = InRange(tbxDALIval);
            if (daliv >= 0) newcmd.DALIval = daliv;
            return newcmd.cmd();
        }
        private int InRange(TextBox tb)
        {
            int wert;
            if (!int.TryParse(tb.Text, out wert)) return 0;
            ValidationRuleInt? vri = tb.Tag as ValidationRuleInt;
            return (wert <= vri?.upper && wert > vri?.lower) ? wert : 0;
        }
        private void btnPortOpen_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                myCOM.PortName = cbxCOMport.SelectedItem.ToString();
                myCOM.Open();
                myCOM.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler);
                lblPortStatus.Content = "connected";
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "IO-Fehler", MessageBoxButton.OK, MessageBoxImage.Exclamation);
            }
        }
        private void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e)
        {
            SerialPort sp = (SerialPort)sender;
            newReceived = sp.ReadExisting();
            //ProtocolParser(newReceived);
            Console.Write("Data received");
            Console.WriteLine(newReceived);
        }
        private void ProtocolParser(string msg)
        {
            if (msg.StartsWith("RDY"))
            {
                int wert = 0;
                bool success = int.TryParse(msg.Substring(4), out wert);
                string Kennung = msg.Substring(3, 1);
                switch (Kennung)
                {
                    case "X":
                        lblXPos.Content = msg.Substring(4);
                        break;
                    case "Y":
                        lblYPos.Content = msg.Substring(4);
                        break;
                }
            }
        }

        private void btnHome_Click(object sender, RoutedEventArgs e)
        {
            string teststring = "RDYY0899";
            vm.UpdatePos(myM, teststring);
            Console.WriteLine ("Testdaten gesendet: " +  teststring);
            ProtocolParser(teststring);
        }
    }
}
