using ScottPlot;
using ScottPlot.WPF;

namespace ProximaAnalizer.ViewModels.Dialog;

internal partial class SingleTracePlotViewModel : ObservableObject, IDialogAware
{
    public SingleTracePlotViewModel(DBDataHelper dBDataHelper)
    {
        this._dBDataHelper = dBDataHelper;
        this.PlotControl = new();
        this._plotHepler = new(this.PlotControl);
        this._plotHepler.InitPlot();
    }
    [ObservableProperty]
    private string _Title = string.Empty;
    private string _BaseTitle = string.Empty;

    private readonly PlotHepler _plotHepler;
    private readonly DBDataHelper _dBDataHelper;
    public DialogCloseListener RequestClose { get; set; }

    [ObservableProperty]
    private WpfPlot _PlotControl;

    [ObservableProperty]
    private ObservableCollection<EventData> _events = [];

    [ObservableProperty]
    private string? _Hint;

    [ObservableProperty]
    private Visibility _alarmVis = Visibility.Visible;

    [ObservableProperty]
    private Visibility _tabVis = Visibility.Visible;

    public bool CanCloseDialog()
    {
        return true;
    }

    public void OnDialogClosed()
    {

    }

    [ObservableProperty]
    private ObservableCollection<string> _Tabs = [];

    [RelayCommand]
    private void SelectTab(string para)
    {
        if (!string.Equals(para, this._BaseTitle))
            this.Title = $"{_BaseTitle} - {para}";
        else
            this.Title = _BaseTitle;

        this.PlotControl.Plot.Clear();

        if (this._DbKeys is null)
            return;
        List<DateTime> time = [];
        List<float> data = [];
        string? key;
        switch (this._DbKeys)
        {
            case Dictionary<string, string> shortKey:
                if (!shortKey.TryGetValue(this._BaseTitle, out key) || string.IsNullOrEmpty(key))
                    return;
                break;

            case Dictionary<string, Dictionary<string, string>> longKey:
                if (!longKey.TryGetValue(this._BaseTitle, out Dictionary<string, string>? lists) || lists is null)
                    return;
                if (!lists.TryGetValue(para, out key) || string.IsNullOrEmpty(key))
                    return;
                break;

            default:
                return;
        }

        if (!_dBDataHelper.GetPMData(["time", key], out List<dynamic>? rawData) || rawData is null || rawData.Count == 0)
        {
            if (!_dBDataHelper.GetSystemData(["time", key], out rawData) || rawData is null || rawData.Count == 0)
                return;
        }

        this.Hint = string.Empty;

        foreach (var item in rawData)
        {
            if (item is not IDictionary<string, object> contents)
                continue;

            if (string.IsNullOrEmpty(this.Hint) && contents[key] is bool b)
                this.Hint = $"True: {Convert.ToSingle(true):0}  False: {Convert.ToSingle(false):0}";

            time.Add(new DateTime((long)contents["time"]));
            data.Add(Convert.ToSingle(contents[key]));
        }

        this._plotHepler.AddLeftLine(time, data, LinePattern.Solid, MarkerStyle.Default, 1, "1E90FF");

        if (Events is not null)
            foreach (var item in Events)
            {
                switch (item.Level)
                {
                    case "Alarm":
                        this._plotHepler.AddAlarmLine(item.Occur_Time, item.Source!);
                        break;
                    case "Warning":
                        this._plotHepler.AddWarningLine(item.Occur_Time, item.Source!);
                        break;
                    default:
                        break;
                }
            }



        this.PlotControl.Plot.Axes.AutoScale();
        this.PlotControl.Refresh();
    }

    private object? _DbKeys;
    private DateTime _start;
    private DateTime _end;
    public void OnDialogOpened(IDialogParameters parameters)
    {
        if (!parameters.TryGetValue("point", out object? obj) || obj is null)
            return;
        if (!parameters.TryGetValue("time", out DateTime? time) || time is null)
            return;
        if (!parameters.TryGetValue("keys", out object? keys) || keys is null)
            return;

        this.Tabs.Clear();
        this._DbKeys = keys;

        switch (obj)
        {
            case KeyValuePair<string, object> singleType:
                this.Title = singleType.Key;
                this._BaseTitle = singleType.Key;
                this.Tabs.Add(singleType.Key);

                break;
            case KeyValuePair<string, ObservableDictionary<string, object>> doubleType:
                this.Title = doubleType.Key;
                this._BaseTitle = doubleType.Key;
                foreach (var item in doubleType.Value)
                    this.Tabs.Add(item.Key);

                break;

            default:
                break;
        }

        _start = time.Value.AddMinutes(-1);
        _end = time.Value.AddMinutes(1);
        this._dBDataHelper.SetTimeRange(_start, _end);


        if (!this._dBDataHelper.GetAlarmData(out List<EventData>? alarms) || alarms is null || alarms.Count == 0)
            this.AlarmVis = Visibility.Collapsed;
        else
            this.Events.AddRange(alarms);

        if (this.Tabs.Count == 1)
        {
            this.SelectTab(this.Tabs.First());
            this.TabVis = Visibility.Collapsed;
        }
    }
}
