using InABox.Core;
using InABox.DynamicGrid;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;

namespace InABox.Wpf.Dashboard.Editor;

/// <summary>
/// Interaction logic for DynamicDashboardEditor.xaml
/// </summary>
public partial class DynamicDashboardEditor : UserControl, INotifyPropertyChanged
{
    private string _dashboardName = "";
    public string DashboardName
    {
        get => _dashboardName;
        set
        {
            _dashboardName = value;
            OnPropertyChanged();
        }
    }

    private string _dashboardGroup = "";
    public string DashboardGroup
    {
        get => _dashboardGroup;
        set
        {
            _dashboardGroup = value;
            OnPropertyChanged();
        }
    }

    private Tuple<string, Type>[] _presentationTypes;
    public Tuple<string, Type>[] PresentationTypes
    {
        get => _presentationTypes;
        [MemberNotNull(nameof(_presentationTypes))]
        set
        {
            _presentationTypes = value;
            OnPropertyChanged();
        }
    }

    private Type? _selectedPresentationType;
    public Type? SelectedPresentationType
    {
        get => _selectedPresentationType;
        set
        {
            _selectedPresentationType = value;
            OnPropertyChanged();

            if(value is not null && value.GetInterfaceDefinition(typeof(IDynamicDashboardDataPresenter<>)) is Type presentationInterface)
            {
                var propertiesType = presentationInterface.GenericTypeArguments[0];
                SetProperties(Activator.CreateInstance(propertiesType)!, value);
            }
        }
    }

    private DynamicDashboardDataComponent DataComponent;

    private object? _presenterProperties;
    private IDynamicDashboardDataPresenter? _presenter;

    public DynamicDashboardEditor(DynamicDashboard dashboard)
    {
        DataComponent = dashboard.DataComponent;

        if(dashboard.DataPresenter is not null)
        {
            _selectedPresentationType = dashboard.DataPresenter.GetType();
        }

        InitializeComponent();

        if(dashboard.DataPresenter is not null)
        {
            SetProperties(dashboard.DataPresenter.Properties, _selectedPresentationType!);
        }

        PresentationTypes = DynamicDashboardUtils.GetPresenterTypes()
            .Select(x => new Tuple<string, Type>(x.GetCaption(), x))
            .ToArray();
    }

    private void SetProperties(object properties, Type presentationType)
    {
        _presenterProperties = properties;

        _presenter = (Activator.CreateInstance(presentationType) as IDynamicDashboardDataPresenter)!;
        _presenter.Properties = _presenterProperties;
        _presenter.IsPreview = true;
        _presenter.DataComponent = DataComponent;

        PresentationEditorControl.Content = _presenter.Setup();
        PresentationEditorControl.Height = _presenter.PreviewHeight;
        RefreshData();
    }

    private void SelectData_Click(object sender, RoutedEventArgs e)
    {
        if (DynamicDashboardDataEditor.Execute(DataComponent))
        {
            RefreshData();
        }
    }

    private void SelectScripts_Click(object sender, RoutedEventArgs e)
    {
        var grid = new DynamicDashboardAdditionalTableGrid();
        grid.Items = DataComponent.AdditionalTables.ToList(x => new DynamicDashboardAdditionalTableEditItem(x));
        grid.Refresh(true, true);
        var dlg = new DynamicContentDialog(grid)
        {
            WindowStartupLocation = WindowStartupLocation.CenterScreen,
            Title = "Edit Additional Scripted Tables",
            CanSave = true
        };
        if(dlg.ShowDialog() == true)
        {
            DataComponent.AdditionalTables = grid.Items.Select(x => x.ToTable()).ToList();
            RefreshData();
        }
    }

    private void RefreshData()
    {
        if(_presenter is not null)
        {
            _presenter.DataComponent = DataComponent;
            DataComponent.RunQueryAsync(100).ContinueWith(data =>
            {
                if(data.Exception is not null)
                {
                    MessageWindow.ShowError("Error loading data.", data.Exception);
                }
                else
                {
                    _presenter.Refresh(data.Result);
                }
            }, TaskScheduler.FromCurrentSynchronizationContext());
        }
    }

    public DynamicDashboard GetDashboard()
    {
        var dashboard = new DynamicDashboard();
        dashboard.DataComponent = DataComponent;

        if(SelectedPresentationType is not null)
        {
            dashboard.DataPresenter = (Activator.CreateInstance(SelectedPresentationType) as IDynamicDashboardDataPresenter)!;
            dashboard.DataPresenter.Properties = _presenterProperties!;
        }
        else
        {
            dashboard.DataPresenter = null;
        }
        return dashboard;
    }
}
