using Microsoft.JSInterop;
using RobotNet.WebApp.Charts.Core;
using RobotNet.WebApp.Charts.Enums;
using RobotNet.WebApp.Charts.Models.Common;
using RobotNet.WebApp.Charts.Models.Common.Dataset;
using RobotNet.WebApp.Charts.Models.PolarAreaChart;

namespace RobotNet.WebApp.Charts.Components;

public partial class PolarAreaChart : RobotNetChart
{
    public PolarAreaChart()
    {
        chartType = ChartType.PolarArea;
    }

    public async Task InitializeAsync(ChartData chartData, IChartOptions chartOptions)
    {
        if (chartData is not null && chartData.Datasets is not null)
        {
            var datasets = chartData.Datasets.OfType<PolarAreaChartDataset>();
            var data = new { chartData.Labels, Datasets = datasets };
            await JSRuntime.InvokeVoidAsync($"window.blazorChart.initialize", Id, chartType, data, (PolarAreaChartOptions)chartOptions);
        }
    }

    public async Task UpdateAsync(ChartData chartData, IChartOptions chartOptions)
    {
        if (chartData is not null && chartData.Datasets is not null)
        {
            var datasets = chartData.Datasets.OfType<PolarAreaChartDataset>();
            var data = new { chartData.Labels, Datasets = datasets };
            await JSRuntime.InvokeVoidAsync($"window.blazorChart.update", Id, data, (PolarAreaChartOptions)chartOptions);
        }
    }

    public async Task UpdateValuesAsync(ChartData chartData)
    {
        if (chartData is not null && chartData.Datasets is not null && chartData.Datasets.Count != 0)
        {
            var datasets = chartData.Datasets.OfType<PolarAreaChartDataset>();
            var data = new { chartData.Labels, Datasets = datasets };
            await JSRuntime.InvokeVoidAsync("window.blazorChart.updateData", Id, data);
        }
    }

    public async Task<ChartData> AddDataAsync(ChartData chartData, string dataLabel, IChartDatasetData data)
    {
        ArgumentNullException.ThrowIfNull(chartData);
        ArgumentNullException.ThrowIfNull(chartData.Datasets);
        ArgumentNullException.ThrowIfNull(data);

        foreach (var dataset in chartData.Datasets)
            if (dataset is PolarAreaChartDataset polarAreaChartDataset && polarAreaChartDataset.Label == dataLabel)
                if (data is PolarAreaChartDatasetData polarAreaChartDatasetData)
                {
                    if (polarAreaChartDatasetData.Data is double dataValue) polarAreaChartDataset.Data?.Add(dataValue);
                    polarAreaChartDataset.BackgroundColor?.Add(polarAreaChartDatasetData.BackgroundColor!);
                }
        await JSRuntime.InvokeVoidAsync($"window.blazorChart.addDatasetData", Id, dataLabel, data);
        return chartData;
    }

    public async Task<ChartData> AddDataAsync(ChartData chartData, string dataLabel, IReadOnlyCollection<IChartDatasetData> data)
    {
        ArgumentNullException.ThrowIfNull(chartData);
        ArgumentNullException.ThrowIfNull(chartData.Datasets);
        ArgumentNullException.ThrowIfNull(chartData.Labels);
        ArgumentNullException.ThrowIfNull(dataLabel);
        ArgumentNullException.ThrowIfNull(data);

        if (string.IsNullOrWhiteSpace(dataLabel))
            throw new Exception($"{nameof(dataLabel)} cannot be empty.");

        if (data.Count == 0)
            throw new Exception($"{nameof(data)} cannot be empty.");

        if (chartData.Datasets.Count != data.Count)
            throw new InvalidDataException("The chart dataset count and the new data points count do not match.");

        if (chartData.Labels.Contains(dataLabel))
            throw new Exception($"{dataLabel} already exists.");

        chartData.Labels.Add(dataLabel);

        foreach (var dataset in chartData.Datasets)
            if (dataset is PolarAreaChartDataset polarAreaChartDataset)
            {
                var chartDatasetData = data.FirstOrDefault(x => x is PolarAreaChartDatasetData polarAreaChartDatasetData && polarAreaChartDatasetData.DatasetLabel == polarAreaChartDataset.Label);

                if (chartDatasetData is PolarAreaChartDatasetData polarAreaChartDatasetData)
                {
                    if (polarAreaChartDatasetData.Data is double dataValue) polarAreaChartDataset.Data?.Add(dataValue);
                    polarAreaChartDataset.BackgroundColor?.Add(polarAreaChartDatasetData.BackgroundColor!);
                }
            }
        await JSRuntime.InvokeVoidAsync($"window.blazorChart.addDatasetsData", Id, dataLabel, data?.Select(x => (PolarAreaChartDatasetData)x));
        return chartData;
    }

    public async Task<ChartData> AddDatasetAsync(ChartData chartData, IChartDataset chartDataset)
    {
        ArgumentNullException.ThrowIfNull(chartData);
        ArgumentNullException.ThrowIfNull(chartData.Datasets);
        ArgumentNullException.ThrowIfNull(chartDataset);

        if (chartDataset is PolarAreaChartDataset polarAreaChartDataset)
        {
            chartData.Datasets.Add(polarAreaChartDataset);
            await JSRuntime.InvokeVoidAsync($"window.blazorChart.addDataset", Id, polarAreaChartDataset);
        }

        return chartData;
    }
}
