@page "/Games/{id:guid}"
@page "/Games/{id:guid}/{panel}"
@page "/Games/Add"
@using LANCommander.Components.FileManagerComponents;
@using LANCommander.Data.Enums;
@using LANCommander.Models;
@using LANCommander.Pages.Games.Components
@using System.IO.Compression;
@attribute [Authorize(Roles = "Administrator")]
@inject GameService GameService
@inject CompanyService CompanyService
@inject GenreService GenreService
@inject TagService TagService
@inject ArchiveService ArchiveService
@inject ScriptService ScriptService
@inject RedistributableService RedistributableService
@inject IMessageService MessageService
@inject NavigationManager NavigationManager
@inject ModalService ModalService

<Layout Class="panel-layout" Style="padding: 24px 0;">
    <Sider Width="200">
        <Menu Mode="@MenuMode.Inline" Style="height: 100%;">
            <MenuItem RouterLink="@($"/Games/{Game.Id}/General")">General</MenuItem>

            @if (Game != null && Game.Id != Guid.Empty)
            {
                <MenuItem RouterLink="@($"/Games/{Game.Id}/Media")">Media</MenuItem>
                <MenuItem RouterLink="@($"/Games/{Game.Id}/Actions")">Actions</MenuItem>
                <MenuItem RouterLink="@($"/Games/{Game.Id}/Multiplayer")">Multiplayer</MenuItem>
                <MenuItem RouterLink="@($"/Games/{Game.Id}/SavePaths")">Save Paths</MenuItem>
                <MenuItem RouterLink="@($"/Games/{Game.Id}/Keys")">Keys</MenuItem>
                <MenuItem RouterLink="@($"/Games/{Game.Id}/Scripts")">Scripts</MenuItem>
                <MenuItem RouterLink="@($"/Games/{Game.Id}/Archives")">Archives</MenuItem>
            }
        </Menu>
    </Sider>

    <Content>
        <PageHeader>
            <PageHeaderTitle>
                @if (Panel == null)
                {
                    <Text>Add New Game</Text>
                }
                else if (PanelDisplayNames.ContainsKey(Panel))
                {
                    @PanelDisplayNames[Panel]
                }
                else
                {
                    @Panel
                }
            </PageHeaderTitle>
            <PageHeaderExtra>
                <Button Type="@ButtonType.Primary" OnClick="Save">Save</Button>
            </PageHeaderExtra>
        </PageHeader>

        <div class="panel-layout-content">
            <div data-panel="General">
                <Form Model="@Game" Layout="@FormLayout.Vertical">
                    <FormItem Label="Title">
                        <Space Style="display: flex">
                            <SpaceItem Style="flex-grow: 1">
                                <Input @bind-Value="@context.Title" BindOnInput="true" />
                            </SpaceItem>
                            <SpaceItem>
                                <GameMetadataLookup ButtonText="Lookup" GameTitle="@context.Title" OnResultSelected="OnGameLookupResultSelected" />
                            </SpaceItem>
                        </Space>
                    </FormItem>
                    <FormItem Label="Sort Title">
                        <Input @bind-Value="@context.SortTitle" />
                    </FormItem>
                    <FormItem Label="Notes">
                        <TextArea @bind-Value="@context.Notes" MaxLength=2000 ShowCount />
                     </FormItem>
                    <FormItem Label="Description">
                        <TextArea @bind-Value="@context.Description" MaxLength=500 ShowCount />
                    </FormItem>
                    <FormItem Label="Released On">
                        <DatePicker TValue="DateTime?" @bind-Value="@context.ReleasedOn" Picker="@DatePickerType.Date" />
                    </FormItem>
                    <FormItem Label="Singleplayer">
                        <Checkbox @bind-Checked="@context.Singleplayer" />
                    </FormItem>
                    <FormItem Label="Developers">
                        <TagsInput Entities="Companies" @bind-Values="Game.Developers" OptionLabelSelector="c => c.Name" TItem="Company" />
                    </FormItem>
                    <FormItem Label="Publishers">
                        <TagsInput Entities="Companies" @bind-Values="Game.Publishers" OptionLabelSelector="c => c.Name" TItem="Company" />
                    </FormItem>
                    <FormItem Label="Genres">
                        <TagsInput Entities="Genres" @bind-Values="Game.Genres" OptionLabelSelector="c => c.Name" TItem="Genre" />
                    </FormItem>
                    <FormItem Label="Tags">
                        <TagsInput Entities="Tags" @bind-Values="Game.Tags" OptionLabelSelector="c => c.Name" TItem="Data.Models.Tag" />
                    </FormItem>
                    <FormItem Label="Redistributables">
                        <TransferInput LeftTitle="Available" RightTitle="Selected" DataSource="Redistributables" TitleSelector="r => r.Name" @bind-Values="Game.Redistributables" />
                    </FormItem>
                </Form>
            </div>

            @if (Game != null && Game.Id != Guid.Empty)
            {
                <div data-panel="Media">
                    <MediaEditor @bind-Values="Game.Media" GameId="Game.Id" GameTitle="@Game.Title" />
                </div>

                <div data-panel="Actions">
                    <ActionEditor @bind-Actions="Game.Actions" GameId="Game.Id" ArchiveId="@LatestArchiveId" />
                </div>

                <div data-panel="Multiplayer">
                    <MultiplayerModeEditor @bind-Value="Game.MultiplayerModes" />
                </div>

                <div data-panel="SavePaths">
                    <SavePathEditor @bind-Value="Game.SavePaths" GameId="Game.Id" ArchiveId="@LatestArchiveId" />
                </div>

                <div data-panel="Keys">
                    <KeysEditor @ref="KeysEditor" @bind-Keys="Game.Keys" GameId="Game.Id" />

                    <Button OnClick="() => KeysEditor.Edit()">Edit</Button>
                </div>

                <div data-panel="Scripts">
                    <ScriptEditor GameId="Game.Id" ArchiveId="@LatestArchiveId" AllowedTypes="new ScriptType[] { ScriptType.Install, ScriptType.Uninstall, ScriptType.NameChange, ScriptType.KeyChange }" />
                </div>

                <div data-panel="Archives">
                    <ArchiveEditor GameId="Game.Id" />
                </div>
            }

        </div>
    </Content>
</Layout>

@if (!String.IsNullOrWhiteSpace(Panel))
{
    <style>
        .panel-layout [data-panel="@Panel"] {
            display: block;
        }
    </style>
}
else
{
    <style>
        .panel-layout [data-panel="General"] {
            display: block;
        }
    </style>
}

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

    bool Loaded = false;
    bool Success;
    string[] Errors = { };

    IEnumerable<Company> Companies;
    IEnumerable<Genre> Genres;
    IEnumerable<Data.Models.Tag> Tags;
    IEnumerable<Redistributable> Redistributables = new List<Redistributable>();
    IEnumerable<TransferItem> RedistributableTargetItems = new List<TransferItem>();
    IEnumerable<string> TargetRedistributables = new List<string>();

    FilePickerDialog ArchiveFilePickerDialog;

    Modal FileSelectorModal;

    private string value = "blazor";

    private Game Game;
    private KeysEditor? KeysEditor;
    private GameMetadataLookup? GameMetadataLookup;

    private Dictionary<string, string> PanelDisplayNames = new Dictionary<string, string>
    {
        { "SavePaths", "Save Paths" }
    };

    private Guid LatestArchiveId
    {
        get
        {
            if (Game != null && Game.Archives != null && Game.Archives.Count > 0)
                return Game.Archives.OrderByDescending(a => a.CreatedOn).FirstOrDefault().Id;
            else
                return Guid.Empty;
        }
    }

    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 OnParametersSetAsync()
    {
        if (!Loaded)
            await LoadData();
    }

    private async Task LoadData() {
        if (Id == Guid.Empty)
            Game = new Game();
        else
            Game = await GameService.Get(Id);

        Companies = await CompanyService.Get();
        Genres = await GenreService.Get();
        Tags = await TagService.Get();
        Redistributables = await RedistributableService.Get();
        RedistributableTargetItems = Redistributables.Select(r => new TransferItem
        {
            Title = r.Name,
            Description = r.Description,
            Key = r.Id.ToString()
        });

        Loaded = true;
    }

    private async Task Save()
    {
        try
        {
            if (Game.Id != Guid.Empty)
            {
                Game = await GameService.Update(Game);

                await MessageService.Success("Game updated!");
            }
            else
            {
                Game = await GameService.Add(Game);

                NavigationManager.LocationChanged += NotifyGameAdded;

                NavigationManager.NavigateTo($"/Games/{Game.Id}");
            }
        }
        catch (Exception ex)
        {
            await MessageService.Error("Could not save!");
        }
    }

    private void NotifyGameAdded(object? sender, LocationChangedEventArgs e)
    {
        NavigationManager.LocationChanged -= NotifyGameAdded;

        MessageService.Success("Game added!");
    }

    private async Task OnGameLookupResultSelected(GameLookupResult result)
    {
        Game.Title = result.IGDBMetadata.Name;
        Game.Description = result.IGDBMetadata.Summary;
        Game.ReleasedOn = result.IGDBMetadata.FirstReleaseDate.GetValueOrDefault().UtcDateTime;
        Game.MultiplayerModes = result.MultiplayerModes.ToList();
        Game.Developers = new List<Company>();
        Game.Publishers = new List<Company>();
        Game.Genres = new List<Genre>();
        Game.Tags = new List<Data.Models.Tag>();

        if (result.IGDBMetadata.GameModes != null && result.IGDBMetadata.GameModes.Values != null)
            Game.Singleplayer = result.IGDBMetadata.GameModes.Values.Any(gm => gm.Name == "Single player");

        if (result.IGDBMetadata.InvolvedCompanies != null && result.IGDBMetadata.InvolvedCompanies.Values != null)
        {
            // Make sure companie
            var developers = result.IGDBMetadata.InvolvedCompanies.Values.Where(c => c.Developer.GetValueOrDefault()).Select(c => c.Company.Value.Name);
            var publishers = result.IGDBMetadata.InvolvedCompanies.Values.Where(c => c.Publisher.GetValueOrDefault()).Select(c => c.Company.Value.Name);

            foreach (var developer in developers)
            {
                Game.Developers.Add(await CompanyService.AddMissing(c => c.Name == developer, new Company { Name = developer }));
            }

            foreach (var publisher in publishers)
            {
                Game.Publishers.Add(await CompanyService.AddMissing(c => c.Name == publisher, new Company { Name = publisher }));
            }
        }

        if (result.IGDBMetadata.Genres != null && result.IGDBMetadata.Genres.Values != null)
        {
            var genres = result.IGDBMetadata.Genres.Values.Select(g => g.Name);

            foreach (var genre in genres)
            {
                Game.Genres.Add(await GenreService.AddMissing(g => g.Name == genre, new Genre { Name = genre }));
            }
        }

        if (result.IGDBMetadata.Keywords != null && result.IGDBMetadata.Keywords.Values != null)
        {
            var tags = result.IGDBMetadata.Keywords.Values.Select(t => t.Name).Take(20);

            foreach (var tag in tags)
            {
                Game.Tags.Add(await TagService.AddMissing(t => t.Name == tag, new Data.Models.Tag { Name = tag }));
            }
        }
    }
}
