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;

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
    {
        public enum Direction
        {
            forward,
            back
        }

        SerialPort myCOM = new SerialPort();

        string[] Ports = SerialPort.GetPortNames();
        MainViewModel vm;


        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;

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

        }
        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)
        {
            string cmdline = BuildCmd('Y');
            if (myCOM.IsOpen) myCOM.Write(cmdline);
        }
        private void btnRight_Click(object sender, RoutedEventArgs e)
        {
            string cmdline = BuildCmd('y');
            if (myCOM.IsOpen) myCOM.Write(cmdline);
        }
        private void btnUp_Click(object sender, RoutedEventArgs e)
        {
            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('Y');
            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();
                lblPortStatus.Content = "connected";
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "IO-Fehler", MessageBoxButton.OK, MessageBoxImage.Exclamation);
            }
        }
    }
}
