using Avalonia;

using Dock.Model.Controls;
using Dock.Model.Core;
using Dock.Model.Mvvm;
using Dock.Model.Mvvm.Controls;

using DynamicData.Binding;

using InkForge.Desktop.Managers;
using InkForge.Desktop.Models;
using InkForge.Desktop.ViewModels.Documents;
using InkForge.Desktop.ViewModels.Tools;

using Microsoft.Extensions.DependencyInjection;

namespace InkForge.Desktop;

public class InkForgeFactory : Factory
{
	private readonly IDock _mainDock;
	private readonly IRootDock _rootDock;
	private readonly WelcomePageDocumentViewModel _welcomePage;
	private readonly WorkspaceTool _workspaceTool;

	public InkForgeFactory(WorkspaceManager workspace)
	{
		_rootDock = CreateRootDock();
		_mainDock = CreateDockDock();
		_mainDock.IsCollapsable = false;
		_mainDock.CanClose = false;

		_welcomePage = CreateWelcomePageDocumentViewModel();
		_workspaceTool = CreateWorkspaceTool();

		workspace.WhenValueChanged(m => m.Workspace).Subscribe(OnWorkspaceChanged);
	}

	public override IRootDock CreateLayout()
	{
		ToolDock toolDock = new()
		{
			Alignment = Alignment.Left,
			Proportion = 0.25,
			VisibleDockables = [_workspaceTool],
		};

		ProportionalDock windowLayoutContent = new()
		{
			Orientation = Orientation.Horizontal,
			VisibleDockables = [toolDock, new ProportionalDockSplitter(), _mainDock]
		};

		_rootDock.VisibleDockables = [windowLayoutContent];
		_rootDock.DefaultDockable = windowLayoutContent;

		return _rootDock;
	}

	private static WelcomePageDocumentViewModel CreateWelcomePageDocumentViewModel()
	{
		return ActivatorUtilities.CreateInstance<WelcomePageDocumentViewModel>(
			Application.Current!.GetValue(App.ServiceProviderProperty)
		);
	}

	private static ViewModels.Tools.WorkspaceTool CreateWorkspaceTool()
	{
		return ActivatorUtilities.CreateInstance<ViewModels.Tools.WorkspaceTool>(
			Application.Current!.GetValue(App.ServiceProviderProperty)
		);
	}

	private void OnWorkspaceChanged(Workspace? workspace)
	{
		IDockable dock = workspace switch
		{
			null => _welcomePage,
			_ => workspace.Services.GetRequiredService<DocumentManager>().Dock,
		};

		AddDockable(_mainDock, dock);
		CloseOtherDockables(dock);
	}
}
