using Converters;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Globalization;
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 VSview.View.CustomControls
{
    /// <summary>
    /// Interaction logic for AnalogControl.xaml
    /// </summary>
    public partial class AnalogControl : UserControl
    {
        public AnalogControl()
        {
            InitializeComponent();

            LayoutRoot.DataContext = this;
        }

        public static readonly DependencyProperty AnalogNameProperty = DependencyProperty.Register("AnalogName", typeof(string), typeof(AnalogControl));
        public string AnalogName
        {
            get { return (string)GetValue(AnalogNameProperty); }
            set { SetValueDp(AnalogNameProperty, value); }
        }

        public static readonly DependencyProperty ParameterAProperty = DependencyProperty.Register("ParameterA", typeof(string), typeof(AnalogControl), new FrameworkPropertyMetadata("", FrameworkPropertyMetadataOptions.Journal | FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, InputValueChanged, null, true, UpdateSourceTrigger.PropertyChanged));
        public string ParameterA
        {
            get { return (string)GetValue(ParameterAProperty); }
            set { SetValueDp(ParameterAProperty, value); }
        }

        public static readonly DependencyProperty ParameterBProperty = DependencyProperty.Register("ParameterB", typeof(string), typeof(AnalogControl), new FrameworkPropertyMetadata("", FrameworkPropertyMetadataOptions.Journal | FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, InputValueChanged, null, true, UpdateSourceTrigger.PropertyChanged));
        public string ParameterB
        {
            get { return (string)GetValue(ParameterBProperty); }
            set { SetValueDp(ParameterBProperty, value); }
        }

        public static readonly DependencyProperty ParameterCProperty = DependencyProperty.Register("ParameterC", typeof(string), typeof(AnalogControl), new FrameworkPropertyMetadata("", FrameworkPropertyMetadataOptions.Journal | FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, InputValueChanged, null, true, UpdateSourceTrigger.PropertyChanged));
        public string ParameterC
        {
            get { return (string)GetValue(ParameterCProperty); }
            set { SetValueDp(ParameterCProperty, value); }
        }

        public static readonly DependencyProperty InputValueProperty = DependencyProperty.Register("InputValue", typeof(int), typeof(AnalogControl), new FrameworkPropertyMetadata(0, FrameworkPropertyMetadataOptions.Journal | FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, InputValueChanged, null, true, UpdateSourceTrigger.PropertyChanged));
        public int InputValue
        {
            get { return (int)GetValue(InputValueProperty); }
            set { SetValueDp(InputValueProperty, value); }
        }

        public static readonly DependencyProperty ResultProperty = DependencyProperty.Register("Result", typeof(string), typeof(AnalogControl), new FrameworkPropertyMetadata("", FrameworkPropertyMetadataOptions.Journal | FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, null, null, true, UpdateSourceTrigger.PropertyChanged));
        public string Result
        {
            get { return (string)GetValue(ResultProperty); }
            set { SetValueDp(ResultProperty, value); }
        }

        private static readonly DependencyProperty SensorIndexProperty = DependencyProperty.Register("SensorIndex", typeof(int), typeof(AnalogControl), new FrameworkPropertyMetadata(0, FrameworkPropertyMetadataOptions.Journal | FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, SelectedIndexChanged, null, true, UpdateSourceTrigger.PropertyChanged));
        private int SensorIndex
        {
            get { return (int)GetValue(SensorIndexProperty); }
            set { SetValueDp(SensorIndexProperty, value); }
        }

        public static readonly DependencyProperty SensorTypesProperty = DependencyProperty.Register("SensorTypes", typeof(List<string>), typeof(AnalogControl), new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.Journal | FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, InputValueChanged, null, true, UpdateSourceTrigger.PropertyChanged));
        public List<string> SensorTypes
        {
            get { return (List<string>)GetValue(SensorTypesProperty); }
            set { SetValueDp(SensorTypesProperty, value); }
        }

        private static readonly DependencyProperty ConvertionExampleProperty = DependencyProperty.Register("ConvertionExample", typeof(string), typeof(AnalogControl), new FrameworkPropertyMetadata("", FrameworkPropertyMetadataOptions.Journal | FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, InputValueChanged, null, true, UpdateSourceTrigger.PropertyChanged));
        private string ConvertionExample
        {
            get { return (string)GetValue(ConvertionExampleProperty); }
            set { SetValueDp(ConvertionExampleProperty, value); }
        }

        public event PropertyChangedEventHandler PropertyChanged;
        void SetValueDp(DependencyProperty property, object value, [System.Runtime.CompilerServices.CallerMemberName] string p = null)
        {
            SetCurrentValue(property, value);
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(p));
        }


        private static void SelectedIndexChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs args)
        {
            AnalogControl AC = dependencyObject as AnalogControl;
            switch (AC.SensorIndex)
            {
                case 0:
                case 1:
                case 2:
                case 3:
                    AC.ConvertionExample = "";
                    break;
                case 4:
                    AC.ConvertionExample = "Ax + B";
                    break;
                case 5:
                    AC.ConvertionExample = "10^(A(x-B))";
                    break;
                case 6:
                    AC.ConvertionExample = "Ax^2 + Bx + C";
                    break;
                default: AC.ConvertionExample = ""; break;
            }
            AC.ConvertValue();
        }


        private static void InputValueChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs args)
        {
            AnalogControl AC = dependencyObject as AnalogControl;
            AC.ConvertValue();
        }



        private void ConvertValue()
        {
            try
            {
                double res = 0;
                switch (SensorIndex)
                {
                    case 0:
                        res = Convert.ToInt32(InputValue);
                        break;
                    case 1:
                        res = MKS902Convertion(InputValue);
                        break;
                    case 2:
                        res = MKS925Convertion(InputValue);
                        break;
                    case 3:
                        res = PCG750Convertion(InputValue);
                        break;
                    case 4:
                        res = LinearConvertion(InputValue, ParameterA, ParameterB);
                        break;
                    case 5:
                        res = ExponentialConvertion(InputValue, ParameterA, ParameterB);
                        break;
                    case 6:
                        res = QuadraticConvertion(InputValue, ParameterA, ParameterB, ParameterC);
                        break;

                    default: break;
                }
                if (res >= 1)
                {
                    Result = res.ToString("#.##");
                }
                else
                {
                    Result = res.ToString("0.00E+0");
                }



            }
            catch (Exception ex) { }
        }


        /// <summary>
        /// Method for converting MKS 902 pressure sensor value
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        private double MKS902Convertion(int input)
        {
            return Convertion.Pressure_Torr_to_mbar((10.0 / 32768.0) * input * 100);
        }

        /// <summary>
        /// Method for converting MKS 925 pressure sensor value 
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        private double MKS925Convertion(int input)
        {
            return Convertion.Pressure_Torr_to_mbar(Math.Pow(10, ((10.0 / 32768.0) * input - 6)));
        }

        /// <summary>
        /// Method for converting Agilent PCG 750 pressure sensor value
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        private double PCG750Convertion(int input)
        {
            return Math.Pow(10, (0.778 * ((10.0 / 32768.0) * input - 6.143)));
        }

        /// <summary>
        /// Metoda pro linearni konverzi
        /// </summary>
        /// <param name="input"></param>
        /// <param name="parA"></param>
        /// <param name="parB"></param>
        /// <returns></returns>
        private double LinearConvertion(int input, string parA, string parB)
        {
            double volt = (10.0 / 32768.0) * input;
            double A = double.Parse(parA.Replace(',', '.'), CultureInfo.InvariantCulture);
            double B;
            if (string.IsNullOrEmpty(parB))
                B = 0;
            else
                B = double.Parse(parB.Replace(',', '.'), CultureInfo.InvariantCulture);

            return (A * volt + B);
        }
        /// <summary>
        /// Metoda pro kvadratickou konverzi
        /// </summary>
        /// <param name="input"></param>
        /// <param name="parA"></param>
        /// <param name="parB"></param>
        /// <param name="parC"></param>
        /// <returns></returns>
        private double QuadraticConvertion(int input, string parA, string parB, string parC)
        {
            double volt = (10.0 / 32768.0) * input;
            double A = double.Parse(parA.Replace(',', '.'), CultureInfo.InvariantCulture);
            double B = double.Parse(parB.Replace(',', '.'), CultureInfo.InvariantCulture);
            double C = double.Parse(parC.Replace(',', '.'), CultureInfo.InvariantCulture);
            return (A * (Math.Pow(volt, 2)) + B * input + C);
        }
        /// <summary>
        /// Metoda pro exponencialni konverzi
        /// </summary>
        /// <param name="input"></param>
        /// <param name="parA"></param>
        /// <param name="parB"></param>
        /// <returns></returns>
        private double ExponentialConvertion(int input, string parA, string parB)
        {
            double volt = (10.0 / 32768.0) * input;
            double A = double.Parse(parA.Replace(',', '.'), CultureInfo.InvariantCulture);
            double B = double.Parse(parB.Replace(',', '.'), CultureInfo.InvariantCulture);
            double exponent = (volt - A) * B;
            return Math.Pow(10, exponent);
        }
    }
}
