using System.Collections.ObjectModel;
using System.Windows;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using ConeCalorimeter.Services;

namespace ConeCalorimeter.ViewModels;

public sealed class MainViewModel : ObservableObject
{
    private PageViewModel _currentPage;
    private readonly IHelpDialogService _helpDialogService;
    private readonly ITcpDeviceConnectionService _tcpDeviceConnectionService;
    private string _deviceStatusText;

    public MainViewModel(
        IExperimentDataService experimentDataService,
        ITcpDeviceConnectionService tcpDeviceConnectionService,
        IReportExportService reportExportService,
        IReportInputPersistenceService reportInputPersistenceService,
        IRealtimeDataExportService realtimeDataExportService,
        IHelpDialogService helpDialogService)
    {
        _helpDialogService = helpDialogService;
        _tcpDeviceConnectionService = tcpDeviceConnectionService;
        _deviceStatusText = tcpDeviceConnectionService.StatusText;
        _tcpDeviceConnectionService.ConnectionStatusChanged += DeviceConnectionStatusChanged;
        var testPage = new TestPageViewModel(experimentDataService, tcpDeviceConnectionService);
        var reportPage = new ReportPageViewModel(
            experimentDataService,
            reportExportService,
            reportInputPersistenceService,
            tcpDeviceConnectionService);
        NavigationItems = [];

        var testItem = new NavigationItemViewModel("测试界面", testPage);
        var cValueItem = new NavigationItemViewModel(
            "C值标定",
            new CValueCalibrationViewModel(
                () => SelectPage(testItem),
                ShowCValueCalibrationHelp,
                ShowBaselineCollectionCompleted,
                ShowCalibrationCompleted,
                tcpDeviceConnectionService));
        var coneRadiationItem = new NavigationItemViewModel(
            "辐射锥设置",
            new ConeRadiationSettingsViewModel(
                () => SelectPage(testItem),
                ShowConeRadiationHelp,
                experimentDataService,
                tcpDeviceConnectionService));
        var smokeDensityItem = new NavigationItemViewModel(
            "烟密度设置",
            new SmokeDensitySettingsViewModel(() => SelectPage(testItem), tcpDeviceConnectionService));
        var realtimeDataItem = new NavigationItemViewModel(
            "实时数据",
            new RealtimeDataViewModel(experimentDataService, realtimeDataExportService, () => SelectPage(testItem)));
        var helpItem = new NavigationItemViewModel(
            "帮助",
            ShowMainHelp);

        NavigationItems.Add(cValueItem);
        NavigationItems.Add(coneRadiationItem);
        NavigationItems.Add(testItem);
        NavigationItems.Add(smokeDensityItem);
        NavigationItems.Add(realtimeDataItem);
        NavigationItems.Add(new NavigationItemViewModel("报表", reportPage));
        NavigationItems.Add(helpItem);

        SelectPageCommand = new RelayCommand<NavigationItemViewModel>(SelectPage);
        _currentPage = testPage;
        SelectPage(testItem);
    }

    public ObservableCollection<NavigationItemViewModel> NavigationItems { get; }

    public IRelayCommand<NavigationItemViewModel> SelectPageCommand { get; }

    public string DeviceStatusText
    {
        get => _deviceStatusText;
        private set => SetProperty(ref _deviceStatusText, value);
    }

    public bool IsDeviceConnected => _tcpDeviceConnectionService.IsConnected;

    public PageViewModel CurrentPage
    {
        get => _currentPage;
        private set => SetProperty(ref _currentPage, value);
    }

    private void SelectPage(NavigationItemViewModel? item)
    {
        if (item is null)
        {
            return;
        }

        foreach (var navigationItem in NavigationItems)
        {
            navigationItem.IsSelected = ReferenceEquals(navigationItem, item);
        }

        if (item.Action is not null)
        {
            item.Action();
            foreach (var navigationItem in NavigationItems)
            {
                navigationItem.IsSelected = ReferenceEquals(navigationItem.Page, CurrentPage);
            }

            return;
        }

        if (item.Page is not null)
        {
            CurrentPage = item.Page;
        }
    }

    private void DeviceConnectionStatusChanged(object? sender, EventArgs e)
    {
        void UpdateStatus()
        {
            DeviceStatusText = _tcpDeviceConnectionService.StatusText;
            OnPropertyChanged(nameof(IsDeviceConnected));
        }

        var dispatcher = Application.Current?.Dispatcher;
        if (dispatcher is not null && !dispatcher.CheckAccess())
        {
            dispatcher.BeginInvoke(UpdateStatus);
            return;
        }

        UpdateStatus();
    }

    private void ShowMainHelp()
    {
        _helpDialogService.ShowHelp(
            "实验帮助",
            "热释放实验帮助",
            "实验步骤：\n"
            + "1.【基样采集】：点击【C值标定】；\n"
            + "    进入界面进行基样采集与C值校准\n\n"
            + "2.辐射锥温度设定：点击【辐射锥设置】；\n\n"
            + "3.温度恒定后，打开隔热板；\n"
            + "    打开风机；\n\n"
            + "4.风速恒定后，点击测试；\n\n"
            + "5.点火时点击【点火开】，试样点燃后点击【点火关】；\n\n"
            + "6.试样完全燃烧后，点击【停止】； 实验结束");
    }

    private void ShowCValueCalibrationHelp()
    {
        _helpDialogService.ShowHelp(
            "C值标定帮助",
            "C值标定 帮助",
            "1.【基线采集】：打开风机，流量稳定后，\n"
            + "    点击基线采集；\n"
            + "2.采集完成时，弹出“基线采集完成”；\n"
            + "3.C值标定：打开甲烷阀门，使用点火器或\n"
            + "    打火机点燃甲烷；\n"
            + "4.调节甲烷流量为8.34L/Min正负0.5L；\n"
            + "5.点击【标定开始】；\n"
            + "6.标定完成后，弹出“标定完成！”；");
    }

    private void ShowBaselineCollectionCompleted()
    {
        _helpDialogService.ShowHelp(
            "C值标定提示",
            "C值标定提示",
            "基线采集完成");
    }

    private void ShowCalibrationCompleted()
    {
        _helpDialogService.ShowHelp(
            "C值标定提示",
            "C值标定提示",
            "标定完成！");
    }

    private void ShowConeRadiationHelp()
    {
        _helpDialogService.ShowHelp(
            "辐射锥帮助",
            "辐射锥帮助",
            "1.【升温】：点击【设置辐射锥温度】；\n"
            + "    输入温度（整数）\n"
            + "2.点击【升温】；\n"
            + "3.等待达到设定温度；");
    }
}
