@page "/Games/{id:guid}/Edit"
@inject GameService GameService
@inject ArchiveService ArchiveService
@inject ScriptService ScriptService
@inject IDialogService DialogService
@inject ISnackbar Snackbar

<MudGrid>
    <MudItem xs="12">
        <MudPaper Class="pa-4">
            <MudForm @bind-IsValid="@Success" @bind-Errors="@Errors">
                <MudTextField @bind-Value="Game.Title" Label="Title" For="@(() => Game.Title)" Adornment="Adornment.End" AdornmentIcon="@Icons.Material.Filled.Search" OnAdornmentClick="LookupGameMetadata" />
                <MudTextField @bind-Value="Game.SortTitle" Label="Sort Title" For="@(() => Game.SortTitle)" />
                <MudTextField @bind-Value="Game.Icon" Label="Icon" Adornment="Adornment.End" AdornmentIcon="@Icons.Material.Filled.Folder" OnAdornmentClick="BrowseForIcon" />
                <MudTextField @bind-Value="Game.Description" Label="Description" For="@(() => Game.Description)" Lines="4" />
                <MudDatePicker @bind-Date="Game.ReleasedOn" Label="Released" />
                <MudCheckBox @bind-Checked="@Game.Singleplayer" Label="Singleplayer" Color="Color.Primary"></MudCheckBox>

                <MudDivider Class="mt-4 mb-4" />

                <MudText Typo="Typo.h6">Developers</MudText>

                <MudChipSet>
                    @foreach (var developer in Game.Developers)
                    {
                        <MudChip>@developer.Name</MudChip>
                    }
                </MudChipSet>

                <MudDivider Class="mt-4 mb-4" />

                <MudText Typo="Typo.h6">Publishers</MudText>

                <MudChipSet>
                    @foreach (var publisher in Game.Publishers)
                    {
                        <MudChip>@publisher.Name</MudChip>
                    }
                </MudChipSet>

                <MudDivider Class="mt-4 mb-4" />

                <MudText Typo="Typo.h6">Genres</MudText>

                <MudChipSet>
                    @foreach (var genre in Game.Genres)
                    {
                        <MudChip>@genre.Name</MudChip>
                    }
                </MudChipSet>

                <MudDivider Class="mt-4 mb-4" />

                <MudText Typo="Typo.h6">Tags</MudText>

                <MudChipSet>
                    @foreach (var tags in Game.Tags)
                    {
                        <MudChip>@tags.Name</MudChip>
                    }
                </MudChipSet>
            </MudForm>
        </MudPaper>
    </MudItem>
</MudGrid>

<MudCard Class="mt-4">
    <MudCardHeader>
        <CardHeaderContent>
            <MudText Typo="Typo.h6">Actions</MudText>
        </CardHeaderContent>
    </MudCardHeader>

    <MudCardContent>
        <ActionEditor Actions="Game.Actions" ArchiveId="Game.Archives.OrderByDescending(a => a.CreatedOn).First().Id" />
    </MudCardContent>
</MudCard>

<MudCard Class="mt-4">
    <MudCardHeader>
        <CardHeaderContent>
            <MudText Typo="Typo.h6">Multiplayer Modes</MudText>
        </CardHeaderContent>
    </MudCardHeader>

    <MudCardContent>
        <MultiplayerModeEditor Game="Game" />
    </MudCardContent>
</MudCard>

<MudCard Class="mt-4">
    <MudCardHeader>
        <CardHeaderContent>
            <MudText Typo="Typo.h6">Keys</MudText>
        </CardHeaderContent>
    </MudCardHeader>

    <MudCardContent>
        <MudGrid>
            <MudItem md="4" Class="mud-typography-align-center">
                <MudText Typo="Typo.overline">Available</MudText>
                <MudText Typo="Typo.body1">@KeysAvailable</MudText>
            </MudItem>

            <MudItem md="4" Class="mud-typography-align-center">
                <MudText Typo="Typo.overline">Claimed</MudText>
                <MudText Typo="Typo.body1">@(Game.Keys.Count - KeysAvailable)</MudText>
            </MudItem>

            <MudItem md="4" Class="mud-typography-align-center">
                <MudText Typo="Typo.overline">Total</MudText>
                <MudText Typo="Typo.body1">@Game.Keys.Count</MudText>
            </MudItem>
        </MudGrid>

        <MudPaper Class="d-flex justify-end" Elevation="0">
            <MudButton Href="@($"/Games/{Id}/Keys")" Color="Color.Primary" Variant="Variant.Filled">View</MudButton>
        </MudPaper>
    </MudCardContent>
</MudCard>

<MudCard Class="mt-4">
    <MudCardHeader>
        <CardHeaderContent>
            <MudText Typo="Typo.h6">Archives</MudText>
        </CardHeaderContent>
    </MudCardHeader>

    <MudCardContent>
        <MudTable Items="Game.Archives" Elevation="0">
            <HeaderContent>
                <MudTh>Version</MudTh>
                <MudTh>Uploaded By</MudTh>
                <MudTh>Uploaded On</MudTh>
                <MudTh>Size</MudTh>
                <MudTh></MudTh>
            </HeaderContent>

            <RowTemplate>
                <MudTd>@context.Version</MudTd>
                <MudTd>@context.CreatedBy?.UserName</MudTd>
                <MudTd>@context.CreatedOn</MudTd>
                <MudTd>
                     @{
                        long size = 0;
                        var path = Path.Combine("Upload", context.ObjectKey);

                        if (File.Exists(path))
                            size = new FileInfo(path).Length;
                    }
                    @ByteSizeLib.ByteSize.FromBytes(size)
                </MudTd>
                <MudTd Class="d-flex flex-nowrap justify-end">
                    <MudIconButton OnClick="() => BrowseArchive(context)" Icon="@Icons.Material.Filled.Folder"></MudIconButton>
                    <MudIconButton OnClick="() => DeleteArchive(context)" Color="Color.Error" Icon="@Icons.Material.Filled.Close"></MudIconButton>
                </MudTd>
            </RowTemplate>
        </MudTable>

        <MudPaper Class="d-flex justify-end" Elevation="0">
            <MudButton OnClick="() => UploadArchive()" StartIcon="@Icons.Material.Filled.Add" Color="Color.Primary" Variant="Variant.Filled">Add</MudButton>
        </MudPaper>
    </MudCardContent>
</MudCard>

<MudCard Class="mt-4">
    <MudCardHeader>
        <CardHeaderContent>
            <MudText Typo="Typo.h6">Scripts</MudText>
        </CardHeaderContent>
    </MudCardHeader>

    <MudCardContent>
        <MudTable Items="Game.Scripts" Elevation="0">
            <HeaderContent>
                <MudTh>Type</MudTh>
                <MudTh>Created By</MudTh>
                <MudTh>Created On</MudTh>
                <MudTh></MudTh>
            </HeaderContent>

            <RowTemplate>
                <MudTd>@context.Type</MudTd>
                <MudTd>@context.CreatedBy?.UserName</MudTd>
                <MudTd>@context.CreatedOn</MudTd>
                <MudTd Class="d-flex flex-nowrap justify-end">
                    <MudIconButton OnClick="() => EditScript(context)" Icon="@Icons.Material.Filled.Edit"></MudIconButton>
                    <MudIconButton OnClick="() => DeleteScript(context)" Color="Color.Error" Icon="@Icons.Material.Filled.Close"></MudIconButton>
                </MudTd>
            </RowTemplate>
        </MudTable>

        <MudPaper Class="d-flex justify-end" Elevation="0">
            <MudButton OnClick="() => EditScript()" Color="Color.Primary" StartIcon="@Icons.Material.Filled.Add" Variant="Variant.Filled">Add</MudButton>
        </MudPaper>
    </MudCardContent>
</MudCard>

<MudFab Color="Color.Primary" Disabled="@(!Success)" OnClick="Save" StartIcon="@Icons.Material.Filled.Save" Style="position: fixed; right: 32px; bottom: 32px;" />

@code {
    [Parameter] public Guid Id { get; set; }

    bool Success;
    string[] Errors = { };
    MudForm Form;

    private Game Game { get; set; }

    private int KeysAvailable { get {
            return Game.Keys.Count(k =>
            {
                return (k.AllocationMethod == KeyAllocationMethod.MacAddress && String.IsNullOrWhiteSpace(k.ClaimedByMacAddress))
                ||
                (k.AllocationMethod == KeyAllocationMethod.UserAccount && k.ClaimedByUser == null);
            });
        } }

    protected override async Task OnInitializedAsync()
    {
        Game = await GameService.Get(Id);
    }

    private async Task Save()
    {
        try
        {
            Game = await GameService.Update(Game);

            Snackbar.Add("Game updated!", Severity.Success);
        }
        catch (Exception ex)
        {
            Snackbar.Add("An unknown error occurred!", Severity.Error);
        }
    }

    private async void BrowseForIcon()
    {
        var parameters = new DialogParameters
        {
            ["ArchiveId"] = Game.Archives.OrderByDescending(a => a.CreatedOn).First().Id
        };

        var dialog = await DialogService.ShowAsync<ArchiveFileSelectorDialog>("File Selector", parameters);
        var result = await dialog.Result;

        if (!result.Canceled)
        {
            Game.Icon = result.Data as string;

            StateHasChanged();
        }
    }

    private async void LookupGameMetadata()
    {
        var parameters = new DialogParameters
        {
            ["GameTitle"] = Game.Title
        };

        var dialog = await DialogService.ShowAsync<GameMetadataLookup>("Game Lookup", parameters);
        var result = await dialog.Result;

        if (!result.Canceled)
        {
            var info = result.Data as Game;

            Game.Title = info.Title;
            Game.Description = info.Description;
            Game.ReleasedOn = info.ReleasedOn;
            Game.MultiplayerModes = info.MultiplayerModes;
            Game.Developers = info.Developers;
            Game.Publishers = info.Publishers;
            Game.Genres = info.Genres;
            Game.Tags = info.Tags;
            Game.Singleplayer = info.Singleplayer;

            StateHasChanged();
        }
    }

    private async void UploadArchive()
    {
        var parameters = new DialogParameters
        {
            ["GameId"] = Game.Id
        };

        var dialog = await DialogService.ShowAsync<ArchiveUploader>("Upload Archive", parameters);

        var result = await dialog.Result;

        await GameService.Context.Entry(Game).Collection(nameof(Game.Archives)).LoadAsync();

        StateHasChanged();
    }

    private async void BrowseArchive(Archive archive)
    {
        var parameters = new DialogParameters
        {
            ["ArchiveId"] = archive.Id
        };

        var dialog = await DialogService.ShowAsync<ArchiveBrowserDialog>("Archive Browser", parameters);
    }

    private async void DeleteArchive(Archive archive)
    {
        bool? result = await DialogService.ShowMessageBox(
            "Delete Archive?",
            "Do you really want to delete this archive? You will not be able to recover it later.",
            "Delete",
            "Cancel"
        );

        if (result == true)
            await ArchiveService.Delete(archive);

        StateHasChanged();
    }

    private async void EditScript(Script script = null)
    {
        if (script == null)
            script = new Script()
            {
                GameId = Game.Id,
                Game = Game
            };

        var parameters = new DialogParameters
        {
            ["Script"] = script
        };

        var dialog = await DialogService.ShowAsync<ScriptEditorDialog>("Edit Script", parameters);

        var result = await dialog.Result;

        await GameService.Context.Entry(Game).Collection(nameof(Game.Archives)).LoadAsync();

        StateHasChanged();
    }

    private async void DeleteScript(Script script)
    {
        bool? result = await DialogService.ShowMessageBox(
            "Delete Script",
            "Do you really want to delete this script? You will not be able to recover it later.",
            "Delete",
            "Cancel"
        );

        if (result == true)
            await ScriptService.Delete(script);

        StateHasChanged();
    }
}
