// Copyright © Selmo Technology GmbH. All Rights Reserved

using Microsoft.AspNetCore.Components;
using SelmoStudio.Hmi.Server.Shared.Components.Chart.Models.Common;
using SelmoStudio.Hmi.Server.Shared.Components.Chart.Models.Scatter;

namespace SelmoStudio.Hmi.Server.Shared.Components.Chart
{
    public partial class LineChartJs
    {
        [Parameter]
        public string Id { get; set; }

        [Parameter]
        public DiagramConfiguration DiagramConfiguration { get; set; } = new DiagramConfiguration
        {
            Title = "Default Title",
            XLabel = "Default X Label",
            YLabel = "Default Y Label"
        };

        [Parameter]
        public IReadOnlyList<GraphConfiguration> GraphConfigurations { get; set; } = Array.Empty<GraphConfiguration>();

        [Parameter]
        public DateTimeOffset? From { get; set; }

        [Parameter]
        public DateTimeOffset? To { get; set; }

        private ScatterChartConfig? _config;
        private Chart? _chart;
        private bool _isInit = false;
        private Dictionary<Guid, int> _graphDictionary = new();

        protected override async Task OnInitializedAsync()
        {
            Initialize();
        }

        public void Initialize()
        {
            _config = CreateConfig();
        }

        private ScatterChartConfig CreateConfig()
        {
            var config = new ScatterChartConfig { Options = CreateOptions(DiagramConfiguration) };

            for (int i = 0; i < GraphConfigurations.Count; i++)
            {
                config.Data.Datasets.Add(new ScatterDataset
                {
                    Label = GraphConfigurations[i].Label,
                    BorderColor = GraphConfigurations[i].Color,
                    Data = GraphConfigurations[i].Data.Select(c => new ScatterXYValue
                    {
                        X = (decimal)c.Timestamp.ToUnixTimeSeconds(),
                        Y = (decimal)c.Value
                    }).ToList(),
                    Tension = 0.1M,
                    PointRadius = 5,
                    ShowLine = true,
                    BackgroundColor = GraphConfigurations[i].Color
                });

                _graphDictionary.Add(GraphConfigurations[i].Id, i);
            }

            return config;
        }

        private Options CreateOptions(DiagramConfiguration configuration)
        {
            var options = new Options
            {
                Animation = false,
                MaintainAspectRatio = true,
                Responsive = true,
                Plugins = new Plugins()
                {
                    Title = new Title()
                    {
                        Display = !string.IsNullOrEmpty(configuration.Title),
                        Text = configuration.Title
                    },
                    Legend = new() { Position = LegendPosition.Right },
                    DataLabels = new DataLabels()
                    {
                        Align = DatalabelsAlign.Start,
                        Anchor = DatalabelsAnchor.Start,
                    }
                },
                Interaction = new SelmoStudio.Hmi.Server.Shared.Components.Chart.Models.Common.Interaction()
                {
                    Intersect = true
                },
                Scales = new Dictionary<string, Axis>()
                {
                    {
                        SelmoStudio.Hmi.Server.Shared.Components.Chart.Models.Common.Scales.XAxisId, new Axis()
                        {
                            Display = true,
                            Title = new AxesTitle()
                            {
                                Display = !string.IsNullOrEmpty(configuration.XLabel),
                                Text = configuration.XLabel
                            },
                            Min = From.HasValue ? From.Value.ToUnixTimeSeconds() : null,
                            Max = To.HasValue ? To.Value.ToUnixTimeSeconds() : null
                        }
                    },
                    {
                        SelmoStudio.Hmi.Server.Shared.Components.Chart.Models.Common.Scales.YAxisId, new Axis()
                        {
                            Display = true,
                            Title = new AxesTitle()
                            {
                                Display = !string.IsNullOrEmpty(configuration.YLabel),
                                Text = configuration.YLabel
                            },
                        }
                    }
                }
            };

            return options;
        }

        protected override void OnInitialized()
        {
            _isInit = true;
        }

        public async Task AddGraph(GraphConfiguration configuration)
        {
            if (!_isInit)
            {
                return;
            }

            _chart?.AddDataset(new ScatterDataset
            {
                Label = configuration.Label,
                BorderColor = configuration.Color,
                Data = configuration.Data.Select(c => new ScatterXYValue
                {
                    X = (decimal)c.Timestamp.ToUnixTimeSeconds(),
                    Y = (decimal)c.Value
                }).ToList(),
                Tension = 0.1M,
                PointRadius = 5,
                ShowLine = true,
                BackgroundColor = configuration.Color
            });

            _graphDictionary.Add(configuration.Id, _graphDictionary.Count);
        }

        public async Task RemoveAllGraph()
        {
            foreach (var entry in _graphDictionary)
            {
                await RemoveGraph(entry.Key);
            }
        }

        public async Task RemoveGraph(Guid graphId)
        {
            if (!_isInit)
            {
                return;
            }

            if (_graphDictionary.TryGetValue(graphId, out var toRemove))
            {
                _chart?.RemoveDataset(toRemove);
                _graphDictionary.Remove(graphId);
            }
        }

        public async Task AddDataPoints(Guid graphId, IReadOnlyList<GraphData> data)
        {
            if (!_isInit)
            {
                return;
            }

            if (_graphDictionary.TryGetValue(graphId, out var index))
            {
                for (var i = 0; i < data.Count; i++)
                {
                    _chart?.AddData(index, (decimal)data[i].Timestamp.ToUnixTimeSeconds(), (decimal)data[i].Value);
                }
            }
        }

        public Task AddDataPoint(Guid graphId, GraphData data)
        {
            return AddDataPoints(graphId, new[] { data });
        }

        public async Task UpdateXScale(DateTimeOffset from, DateTimeOffset to)
        {
            _chart?.UpdateXScale(
                from.Equals(DateTimeOffset.MinValue) ? null : (decimal)from.ToUnixTimeSeconds(),
                to.Equals(DateTimeOffset.MaxValue) ? null : (decimal)to.ToUnixTimeSeconds());
        }
    }
}