using System;
using System.Collections.Generic;
using System.Linq;
using System.ComponentModel;
using SciChart.Charting.Model.DataSeries;
using SciChart.Charting.Visuals.RenderableSeries;
using System.Windows.Media;
using System.Threading.Tasks;
using SciChart.Charting.Visuals.Annotations;
using System.Windows;
using System.Collections.ObjectModel;
using SciChart.Charting.Model.ChartSeries;
using SciChart.Charting.Visuals.PointMarkers;
using Aitex.Core.Util;

namespace SicUI.Models.PMs.Charting
{
    public class ChartDataLineXV2 : LineRenderableSeriesViewModel, INotifyPropertyChanged
    {

        private string[] _dbModules = { "PM1", "PM2" };

        public string Time { get; set; }

        public string RecipeName { get; set; }

        public string UniqueId { get; set; }

        public string ProcessGuid { get; set; }

        public string Module { get; set; }
        public string RecName { get; set; }

        public List<Tuple<double, double>> Points
        {
            get
            {
                lock (_lockData)
                {
                    return _queueRawData.ToList();
                }
            }
        }

        public string DataSource { get; set; }
        public string DataName { get; set; }

        public string DisplayName
        {
            get
            {
                return DataSeries.SeriesName;
            }
            set
            {
                DataSeries.SeriesName = value;
            }
        }
        public double LineThickness
        {
            get
            {
                return StrokeThickness;
            }
            set
            {
                var i = Convert.ToInt32(value);
                if (i < 1) i = 1;
                if (i > 100) i = 100;
                StrokeThickness = i;
                OnPropertyChanged("LineThickness");
            }
        }

        private double _dataFactor = 1.0;
        public double DataFactor
        {
            get => _dataFactor;
            set
            {
                if (Math.Abs(_dataFactor - value) > 0.001)
                {
                    _dataFactor = value;
                    OnPropertyChanged(nameof(DataFactor));
                    UpdateChartSeriesValue();
                }
            }
        }

        private double _dataOffset = 0;
        public double DataOffset
        {
            get => _dataOffset;
            set
            {
                if (Math.Abs(_dataOffset - value) > 0.001)
                {
                    _dataOffset = value;
                    OnPropertyChanged(nameof(DataOffset));
                    UpdateChartSeriesValue();
                }
            }
        }
        private double _dataxOffset = 0;
        public double DataXOffset
        {
            get => _dataxOffset;
            set
            {
                _dataxOffset = value;
                OnPropertyChanged(nameof(DataXOffset));
                RePaintChartSeriesValue();
            }
        }
        private int _capacity = 10000;

        public int Capacity
        {
            get { return _capacity; }
            set
            {
                _capacity = value;
                //DataSeries.FifoCapacity = value;
                if (_queueRawData != null)
                {
                    _queueRawData.FixedSize = value;
                }

            }
        }
        private object _lockData = new object();

        private FixSizeQueue<Tuple<double, double>> _queueRawData;

        public ChartDataLineXV2(string dataName)
        : this(dataName, dataName, Colors.Blue)
        {
            Module = "System";
            StyleKey = "LineStyle";
            foreach (var dbModule in _dbModules)
            {
                if (dataName.StartsWith(dbModule))
                {
                    Module = dbModule;
                    break;
                }
            }
        }

        public ChartDataLineXV2(string dataName, string displayName, Color seriesColor)
        {
            UniqueId = Guid.NewGuid().ToString();

            //PointMarker = new EllipsePointMarker() { Width = 5, Height = 5 };
            
            _queueRawData = new FixSizeQueue<Tuple<double, double>>(_capacity);

            XAxisId = "DefaultAxisId";
            YAxisId = "DefaultAxisId";
            DataSeries = new XyDataSeries<double, double>(0);

            DisplayName = displayName;

            DataName = dataName;

            Stroke = seriesColor;

            IsVisible = true;
            DataOffset = 0;
            LineThickness = 1;
            DataFactor = 1;
        }

        public void Append(double xvalue, double value)
        {
            lock (_lockData)
            {
                _queueRawData.Enqueue(Tuple.Create(xvalue, value));
                var series = DataSeries as XyDataSeries<double, double>;
                if (series != null)
                {
                    series.Append(xvalue, value * _dataFactor + _dataOffset);
                }
            }
        }

        public void UpdateChartSeriesValue()
        {
            lock (_lockData)
            {
                using (DataSeries.SuspendUpdates())
                {
                    XyDataSeries<double, double> s = DataSeries as XyDataSeries<double, double>;
                    for (int i = 0; i < s.Count; i++)
                    {
                        s.Update(i, _queueRawData.ElementAt(i).Item2 * _dataFactor + _dataOffset);
                    }
                }
            }
        }

        public void RePaintChartSeriesValue()
        {
            lock (_lockData)
            {
                using (DataSeries.SuspendUpdates())
                {
                    DataSeries.Clear();
                    var series = DataSeries as XyDataSeries<double, double>;
                    for (int i = 0; i < _queueRawData.Count; i++)
                    {
                        series.Append(_queueRawData.ElementAt(i).Item1 + DataXOffset, _queueRawData.ElementAt(i).Item2 * _dataFactor + _dataOffset);
                    }
                }
            }
        }
    }
}
