@page "/Games"
@using AntDesign.TableModels;
@using LANCommander.Extensions;
@using System.ComponentModel.DataAnnotations;
@using LANCommander.Models
@using LANCommander.Pages.Games.Components
@using Microsoft.AspNetCore.Components.Server.ProtectedBrowserStorage;
@using Microsoft.EntityFrameworkCore;
@using System.Web
@attribute [Authorize]
@inject GameService GameService
@inject NavigationManager NavigationManager
@inject ModalService ModalService
@inject IMessageService MessageService

<PageHeader Title="Games" Subtitle="@Games.Count().ToString()">
    <PageHeaderExtra>
        <Space Direction="DirectionVHType.Horizontal">
            @if (Selected != null && Selected.Count() > 0)
            {
                <SpaceItem>
                    <Button OnClick="() => AddToCollection()" Type="@ButtonType.Primary">Add to Collection</Button>
                </SpaceItem>
            }
            <SpaceItem>
                <Search Placeholder="Search" @bind-Value="Search" BindOnInput DebounceMilliseconds="250" OnChange="SearchChanged" />
            </SpaceItem>
            <SpaceItem>
                <Button OnClick="() => Add()" Type="@ButtonType.Primary">Add Game</Button>
            </SpaceItem>
        </Space>
    </PageHeaderExtra>
</PageHeader>

<TableColumnPicker @ref="Picker" Key="Games" @bind-Visible="ColumnPickerVisible" />

<Table TItem="Game" DataSource="@Games" @bind-SelectedRows="Selected" Loading="@Loading" PageSize="@PageSize" PageIndex="@PageIndex" OnPageIndexChange="PageIndexChanged" OnPageSizeChange="PageSizeChanged" Responsive>
    <Selection Key="@(context.Id.ToString())" />
    <Column TData="string" Title="Icon" Hidden="@(Picker.IsColumnHidden("Icon"))">
        <Image Src="@GetIcon(context)" Height="32" Width="32" Preview="false"></Image>
    </Column>
    
    <PropertyColumn Property="g => g.Title" Sortable Filterable Hidden="@(Picker.IsColumnHidden("Title"))" />
    
    <PropertyColumn Property="g => g.SortTitle" Title="Sort Title" Sortable Filterable Hidden="@(Picker.IsColumnHidden("Sort Title", false))" />
    
    <PropertyColumn Property="g => g.ReleasedOn" Format="MM/dd/yyyy" Sortable Filterable Hidden="@(Picker.IsColumnHidden("Released On"))" />
    
    <PropertyColumn Property="g => g.CreatedOn" Format="MM/dd/yyyy hh:mm tt" Sortable Hidden="@(Picker.IsColumnHidden("Created On"))" />
    
    <PropertyColumn Property="g => g.CreatedBy" Sortable Hidden="@(Picker.IsColumnHidden("Created By"))">
        @context.CreatedBy?.UserName
    </PropertyColumn>
    
    <PropertyColumn Property="g => g.UpdatedOn" Format="MM/dd/yyyy hh:mm tt" Sortable Hidden="@(Picker.IsColumnHidden("Updated On", false))" />
    
    <PropertyColumn Property="g => g.UpdatedBy" Sortable Hidden="@(Picker.IsColumnHidden("Updated By", false))">
        @context.UpdatedBy?.UserName
    </PropertyColumn>
    
    <PropertyColumn Property="g => g.Singleplayer" Sortable Filterable Hidden="@(Picker.IsColumnHidden("Singleplayer", false))">
        <Checkbox Disabled="true" Checked="context.Singleplayer" />
    </PropertyColumn>
    
    <Column TData="bool" Title="Multiplayer" Hidden="@(Picker.IsColumnHidden("Multiplayer", false))">
        <Checkbox Disabled="true" Checked="context.MultiplayerModes?.Count > 0" />
    </Column>

    <Column TData="int" Title="Total Keys" Hidden="@(Picker.IsColumnHidden("Total Keys"))">
        @context.Keys?.Count
    </Column>

    <Column TData="int" Title="Keys Allocated" Hidden="@(Picker.IsColumnHidden("Keys Allocated"))">
        @context.Keys?.Count(k => k.ClaimedOn.HasValue)
    </Column>

    <Column TData="string[]" Title="Developers" Hidden="@(Picker.IsColumnHidden("Developers", false))">
        @foreach (var dev in context.Developers)
        {
            <Tag>@dev.Name</Tag>
        }
    </Column>

    <Column TData="string[]" Title="Publishers" Hidden="@(Picker.IsColumnHidden("Publishers", false))">
        @foreach (var pub in context.Publishers)
        {
            <Tag>@pub.Name</Tag>
        }
    </Column>

    <Column TData="string[]" Title="Genres" Hidden="@(Picker.IsColumnHidden("Genres", false))">
        @foreach (var genre in context.Genres)
        {
            <Tag>@genre.Name</Tag>
        }
    </Column>

    <Column TData="Data.Enums.MultiplayerType[]" Title="Multiplayer Modes" Hidden="@(Picker.IsColumnHidden("Multiplayer Modes"))">
        @foreach (var mode in context.MultiplayerModes.Select(mm => mm.Type).Distinct())
        {
            <Tag>@mode.GetDisplayName()</Tag>
        }
    </Column>

    <ActionColumn Title="" Style="text-align: right">
        <TitleTemplate>
            <div style="text-align: right">
                <Button Icon="@IconType.Outline.Edit" Type="@ButtonType.Text" OnClick="() => OpenColumnPicker()" />
            </div>
        </TitleTemplate>
        <ChildContent>
            <Space Direction="DirectionVHType.Horizontal">
                <SpaceItem>
                    <Button OnClick="() => ViewSaves(context)">Saves</Button>
                </SpaceItem>
                <SpaceItem>
                    <a href="/Games/@(context.Id)" class="ant-btn ant-btn-primary">Edit</a>
                </SpaceItem>
                <SpaceItem>
                    <Popconfirm OnConfirm="() => Delete(context)" Title="Are you sure you want to delete this game?">
                        <Button Icon="@IconType.Outline.Close" Type="@ButtonType.Text" Danger />
                    </Popconfirm>
                </SpaceItem>
            </Space>
        </ChildContent>
    </ActionColumn>
</Table>

 @code {
    IEnumerable<Game> Games { get; set; } = new List<Game>();

    bool Loading = true;

    string Search = "";
    string Url;

    bool Visibility = false;

    IEnumerable<Game> Selected;

    TableColumnPicker Picker;
    bool ColumnPickerVisible = false;

    int PageIndex = 1;
    int PageSize = 25;

    protected override async Task OnInitializedAsync()
    {
        Url = NavigationManager.Uri;
        NavigationManager.LocationChanged += LocationChanged;
        LoadTableParameter();
        await LoadData();

        Loading = false;
    }

    private async Task LoadData()
    {
        Games = await GameService.Get(g => g.Title.ToLower().Contains(Search.ToLower().Trim()) || g.SortTitle.ToLower().Contains(Search.ToLower().Trim())).OrderBy(g => String.IsNullOrWhiteSpace(g.SortTitle) ? g.Title : g.SortTitle).ToListAsync();

        await InvokeAsync(StateHasChanged);
    }

    private async void LocationChanged(object sender, LocationChangedEventArgs e)
    {
        Url = e.Location;
        LoadTableParameter();
        await LoadData();
    }

    private void LoadTableParameter()
    {
        var uri = NavigationManager.ToAbsoluteUri(Url);
        var query = HttpUtility.ParseQueryString(uri.Query);

        PageIndex = int.TryParse(query["Page"], out var index) ? index > 0 ? index : 1 : 1;
        PageSize = int.TryParse(query["Size"], out var size) ? size > 0 ? size : 25 : 25;

        if (query["Search"] != null)
            Search = query["Search"];
        else
            Search = "";
    }

    private void PageIndexChanged(PaginationEventArgs args)
    {
        NavigationManager.NavigateTo($"Games?Page={args.Page}&Size={args.PageSize}{(Search != "" ? "&Search=" + Search : "")}");
    }

    private void PageSizeChanged(PaginationEventArgs args)
    {
        NavigationManager.NavigateTo($"Games?Page={args.Page}&Size={args.PageSize}{(Search != "" ? "&Search=" + Search : "")}");
    }

    private void SearchChanged()
    {
        NavigationManager.NavigateTo($"Games?Search={Search}");
    }

    private string GetIcon(Game game)
    {
        var media = game?.Media?.FirstOrDefault(m => m.Type == Data.Enums.MediaType.Icon);

        if (media != null)
            return $"/api/Media/{media.Id}/Download?fileId={media.FileId}";
        else
            return "/favicon.ico";
    }

    private void Add()
    {
        NavigationManager.NavigateTo("/Games/Add");
    }

    private void ViewSaves(Game game)
    {
        NavigationManager.NavigateTo($"/Games/{game.Id}/Saves", true);
    }

    private void Edit(Game game)
    {
        NavigationManager.NavigateTo($"/Games/{game.Id}/Edit", true);
    }

    private async Task Delete(Game game)
    {
        Games = new List<Game>();

        Loading = true;

        try
        {
            await GameService.Delete(game);
        }
        catch (Exception ex)
        {
            MessageService.Error("Could not delete the game!");
        }

        Games = await GameService.Get(x => true).OrderBy(g => String.IsNullOrWhiteSpace(g.SortTitle) ? g.Title : g.SortTitle).ToListAsync();

        Loading = false;
    }

    private async void AddToCollection()
    {
        var modalOptions = new ModalOptions()
            {
                Title = "Add to Collection",
                Maximizable = false,
                DefaultMaximized = false,
                Closable = true,
                OkText = "Add"
            };

        var options = new AddToCollectionOptions()
        {
            GameIds = Selected.Select(g => g.Id)
        };

        var modalRef = await ModalService.CreateModalAsync<AddToCollectionDialog, AddToCollectionOptions, Collection>(modalOptions, options);

        modalRef.OnOk = async (collection) =>
        {
            Selected = null;
            await LoadData();
        };
    }

    private async Task OpenColumnPicker()
    {
        ColumnPickerVisible = true;
    }

    private async Task CloseColumnPicker()
    {
        ColumnPickerVisible = false;
    }

    public void Dispose()
    {
        NavigationManager.LocationChanged -= LocationChanged;
    }
}
