@page "/server/{ServerUuid}/{Route?}"
@using PteroConsole.NET
@using Task = System.Threading.Tasks.Task
@using Moonlight.App.Repositories.Servers
@using PteroConsole.NET.Enums
@using Microsoft.EntityFrameworkCore
@using Logging.Net
@using Moonlight.App.Database.Entities
@using Moonlight.App.Helpers
@using Moonlight.App.Repositories
@using Moonlight.App.Services
@using Moonlight.Shared.Components.Xterm
@using Moonlight.Shared.Components.ServerControl
@using Newtonsoft.Json

@inject ImageRepository ImageRepository
@inject ServerRepository ServerRepository
@inject WingsConsoleHelper WingsConsoleHelper
@inject MessageService MessageService
@inject ServerService ServerService
@inject NavigationManager NavigationManager

@implements IDisposable

<LazyLoader Load="LoadData">
    @if (CurrentServer == null)
    {
        <div class="d-flex justify-content-center flex-center">
            <div class="card">
                <img src="/assets/media/svg/nodata.svg" class="card-img-top w-50 mx-auto pt-5" alt="Not found image"/>
                <div class="card-body text-center">
                    <h1 class="card-title">
                        <TL>Server not found</TL>
                    </h1>
                    <p class="card-text fs-4">
                        <TL>A server with that id cannot be found or you have no access for this server</TL>
                    </p>
                </div>
            </div>
        </div>
    }
    else
    {
        if (NodeOnline)
        {
            if (Console.ConnectionState == ConnectionState.Connected)
            {
                if (Console.ServerState == ServerState.Installing)
                {
                    <div class="card">
                        <div class="card-body">
                            <div class="mb-10">
                                <div class="fs-2hx fw-bold text-gray-800 text-center mb-13">
                                    <span class="me-2">
                                        <TL>Server installation is currently running</TL>
                                    </span>
                                </div>
                            </div>
                            <Terminal @ref="InstallConsole"></Terminal>
                        </div>
                    </div>
                }
                else if (CurrentServer.Installing)
                {
                    <div class="card">
                        <div class="card-body">
                            <div class="mb-10">
                                <div class="fs-2hx fw-bold text-gray-800 text-center mb-13">
                                    <span class="me-2">
                                        <TL>Server installation is currently running</TL>
                                    </span>
                                </div>
                            </div>
                            <Terminal @ref="InstallConsole"></Terminal>
                        </div>
                    </div>
                }
                else
                {
                    <CascadingValue Value="Console">
                        <CascadingValue Value="CurrentServer">
                            <CascadingValue Value="Tags">
                                <CascadingValue Value="Node">
                                    <CascadingValue Value="Image">
                                        <CascadingValue Value="NodeAllocation">
                                            @{
                                                var index = 0;

                                                switch (Route)
                                                {
                                                    case "files":
                                                        index = 1;
                                                        break;
                                                    case "backups":
                                                        index = 2;
                                                        break;
                                                    case "network":
                                                        index = 3;
                                                        break;
                                                    case "addons":
                                                        index = 4;
                                                        break;
                                                    case "settings":
                                                        index = 5;
                                                        break;
                                                    default:
                                                        index = 0;
                                                        break;
                                                }
                                            }

                                            <ServerNavigation Index="index">
                                                @switch (Route)
                                                {
                                                    case "files":
                                                        <ServerFiles></ServerFiles>
                                                        break;
                                                    case "backups":
                                                        <ServerBackups></ServerBackups>
                                                        break;
                                                    case "network":
                                                        <ServerNetwork></ServerNetwork>
                                                        break;
                                                    case "addons":
                                                        <ServerAddons></ServerAddons>
                                                        break;
                                                    case "settings":
                                                        <ServerSettings></ServerSettings>
                                                        break;
                                                    default:
                                                        <ServerConsole></ServerConsole>
                                                        break;
                                                }
                                            </ServerNavigation>
                                        </CascadingValue>
                                    </CascadingValue>
                                </CascadingValue>
                            </CascadingValue>
                        </CascadingValue>
                    </CascadingValue>
                }
            }
            else
            {
                <div class="alert alert-info">
                    <TL>Connecting</TL>
                </div>
            }
        }
        else
        {
            <div class="d-flex justify-content-center flex-center">
                <div class="card">
                    <img src="/assets/media/svg/serverdown.svg" class="card-img-top w-50 mx-auto pt-5" alt="Not found image"/>
                    <div class="card-body text-center">
                        <h1 class="card-title">
                            <TL>Node offline</TL>
                        </h1>
                        <p class="card-text fs-4">
                            <TL>The node the server is running on is currently offline</TL>
                        </p>
                    </div>
                </div>
            </div>
        }
    }
</LazyLoader>

@code
{

    [Parameter]
    public string ServerUuid { get; set; }

    [CascadingParameter]
    public User User { get; set; }

    [Parameter]
    public string? Route { get; set; }

    private PteroConsole? Console;
    private Server? CurrentServer;
    private Node Node;
    private bool NodeOnline = false;
    private Image Image;
    private NodeAllocation NodeAllocation;
    private string[] Tags;

    private Terminal? InstallConsole;

    protected override void OnInitialized()
    {
        Console = new();

        Console.OnConnectionStateUpdated += (_, _) => { InvokeAsync(StateHasChanged); };
        Console.OnServerResourceUpdated += async (_, _) => { await InvokeAsync(StateHasChanged); };
        Console.OnServerStateUpdated += async (_, _) => { await InvokeAsync(StateHasChanged); };

        Console.RequestToken += (_) => WingsConsoleHelper.GenerateToken(CurrentServer!);

        Console.OnMessage += async (_, s) =>
        {
            if (Console.ServerState == ServerState.Installing)
            {
                if (InstallConsole != null)
                {
                    await InstallConsole.WriteLine(s);
                }
            }
        };
    }

    private async Task LoadData(LazyLoader lazyLoader)
    {
        await lazyLoader.SetText("Requesting server data");

        try
        {
            var uuid = Guid.Parse(ServerUuid);

            CurrentServer = ServerRepository
                .Get()
                .Include(x => x.Allocations)
                .Include(x => x.Image)
                .Include(x => x.Node)
                .Include(x => x.Variables)
                .Include(x => x.MainAllocation)
                .Include(x => x.Owner)
                .First(x => x.Uuid == uuid);
        }
        catch (Exception)
        {
            // ignored
        }

        if (CurrentServer != null)
        {
            if (CurrentServer.Owner.Id != User!.Id && !User.Admin)
                CurrentServer = null;
        }

        if (CurrentServer != null)
        {
            await lazyLoader.SetText("Checking node online status");

            NodeOnline = await ServerService.IsHostUp(CurrentServer);

            if (NodeOnline)
            {
                await lazyLoader.SetText("Requesting tags");

                var image = ImageRepository
                    .Get()
                    .First(x => x.Id == CurrentServer.Image.Id);

                Tags = JsonConvert.DeserializeObject<string[]>(image.TagsJson) ?? Array.Empty<string>();
                Image = image;

                await lazyLoader.SetText("Connecting to console");

                await WingsConsoleHelper.ConnectWings(Console!, CurrentServer);

                MessageService.Subscribe<Index, Server>($"server.{CurrentServer.Uuid}.installcomplete", this, server =>
                {
                    Task.Run(() => { NavigationManager.NavigateTo(NavigationManager.Uri); });

                    return Task.CompletedTask;
                });
            }
        }
        else
        {
            Logger.Debug("Server is null");
        }
    }

    public void Dispose()
    {
        if (CurrentServer != null)
        {
            MessageService.Unsubscribe($"server.{CurrentServer.Uuid}.installcomplete", this);
        }
    }
}