@using System.Net.Http.Headers
@using Microsoft.AspNetCore.Components.WebAssembly.Authentication

@inject IHttpClientFactory HttpClientFactory
@inject IJSRuntime JSRuntime
@inject NavigationManager Nav
@inject ISnackbar Snackbar

<div class="d-flex flex-column h-100 w-100">
    <span Class="title">@MapName</span>
    <div class="d-flex flex-grow-1 w-100 flex-column">
        <div class="map-item">
            <img src="@imageSrc" alt="map image" onerror="this.onerror=null; this.src='/images/Image-not-found.png';" />
        </div>
        <div class="d-flex flex-row m-3 align-items-center justify-content-between">
            <MudText Typo="Typo.h5">Map's Image</MudText>
            <div class="d-flex flex-row">
                <MudIconButton Class="me-3" Size="Size.Small" Variant="Variant.Filled" Icon="@Icons.Material.Filled.Download" Color="Color.Primary" Disabled="@Disable" OnClick="@(async () => await DownloadImage())" />
                <MudIconButton Class="me-3" Size="Size.Small" Variant="Variant.Filled" Icon="@Icons.Material.Filled.Upload" Color="Color.Primary" Disabled="@Disable" OnClick="OpenUpdateMapImage" />
            </div>
        </div>
        <MudButton StartIcon="@Icons.Material.Filled.BorderColor" Class="m-2" Size="Size.Small" Variant="Variant.Filled" Color="Color.Primary" OnClick="@(() => Nav.NavigateTo($"/navigation-maps/editor/{MapId}"))" Disabled="Disable">
            Design
        </MudButton>
        <MudButton StartIcon="@Icons.Material.Filled.Settings" Class="m-2" Size="Size.Small" Variant="Variant.Filled" Color="Color.Primary" OnClick="@(() => Nav.NavigateTo($"/navigation-maps/settings/{MapId}"))" Disabled="Disable">
            Setting
        </MudButton>
        <MudButton StartIcon="@Icons.Material.Filled.LocationOn" Class="m-2" Size="Size.Small" Variant="Variant.Filled" Color="Color.Primary" OnClick="@(() => Nav.NavigateTo($"/navigation-maps/elements/{MapId}"))" Disabled="Disable">
            Element
        </MudButton>
        <MudButton StartIcon="@Icons.Material.Filled.FileDownload" Class="m-2" Size="Size.Small" Variant="Variant.Filled" Color="Color.Primary" Disabled="Disable" OnClick="ExportMap">
            Export
        </MudButton>
        <MudSpacer />
        @* <LoginDisplay /> *@
    </div>
</div>

<MudDialog @bind-Visible="@IsUpdateMapImageVisable">
    <TitleContent>
        <MudText Typo="Typo.h6">
            Update Map's Image
        </MudText>
    </TitleContent>
    <DialogContent>
        <div class="d-flex flex-column w-100 h-100 px-3">
            <div class="d-flex flex-row mb-2">
                <InputFile id="fileMapImageCreate" OnChange="MapImageChanged" accept=".png" hidden />
                <MudButton HtmlTag="label"
                           Variant="Variant.Filled"
                           Color="Color.Primary"
                           StartIcon="@Icons.Material.Filled.CloudUpload"
                           for="fileMapImageCreate">
                    Map Image
                </MudButton>
            </div>
            <div class="d-flex mb-2">
                <div class="map-update-item">
                    <img alt="Map Image" src="@ImagePreview" style="image-rendering: pixelated;" />
                </div>
            </div>
        </div>
    </DialogContent>
    <DialogActions>
        <MudButton OnClick="@(() => IsUpdateMapImageVisable = false)" Variant="Variant.Filled">Cancel</MudButton>
        <MudButton Color="Color.Primary" OnClick="UpdateMapImage" Variant="Variant.Filled">Update</MudButton>
    </DialogActions>
</MudDialog>

@code {
    [Parameter]
    public EventCallback<Guid> MapImageChangedCallBack { get; set; }

    private bool Disable = true;
    private string imageSrc = "/images/Image-not-found.png";
    private string MapName = "Map preview";
    private Guid MapId = Guid.Empty;

    private string ImagePreview = "";
    private IBrowserFile? MapImageChange;

    private bool IsUpdateMapImageVisable;

    private HttpClient Http = default!;

    protected override void OnInitialized()
    {
        base.OnInitialized();
        Http = HttpClientFactory.CreateClient("MapManagerAPI");
    }

    public void SetMapPreview(MapInfoDto? map)
    {
        if (map is null)
        {
            Disable = true;
            MapName = "Map preview";
            imageSrc = "/images/Image-not-found.png";
            MapId = Guid.Empty;
        }
        else
        {
            imageSrc = $"{Http.BaseAddress}api/Images/map/{map.Id}?t={DateTime.Now}";
            MapName = map.Name;
            MapId = map.Id;
            Disable = false;
        }
        StateHasChanged();
    }

    private async Task DownloadImage()
    {
        try
        {
            var response = await Http.GetAsync(imageSrc);

            if (response.IsSuccessStatusCode)
            {
                var fileBytes = await response.Content.ReadAsByteArrayAsync();

                var base64Data = Convert.ToBase64String(fileBytes);
                var mimeType = "image/png";
                var url = $"data:{mimeType};base64,{base64Data}";

                await JSRuntime.InvokeVoidAsync("DownloadImage", url, $"{MapName}.png");
            }
            else Snackbar.Add("Không thể tải ảnh map", Severity.Warning);
        }
        catch (Exception ex)
        {
            Snackbar.Add($"Không thể tải ảnh map: {ex.Message}", Severity.Warning);
        }
    }

    private void OpenUpdateMapImage()
    {
        ImagePreview = imageSrc;
        MapImageChange = null;
        IsUpdateMapImageVisable = true;
        StateHasChanged();
    }

    public async Task<string> UploadMedia(IBrowserFile file)
    {
        var path = Path.Combine(Path.GetTempPath(), MapName);
        await using var fs = new FileStream(path, FileMode.Create);
        await file.OpenReadStream(file.Size).CopyToAsync(fs);
        var bytes = new byte[file.Size];
        fs.Position = 0;
        await fs.ReadAsync(bytes);
        fs.Close();
        File.Delete(path);
        return $"data:{file.ContentType};base64,{Convert.ToBase64String(bytes)}";
    }

    private async Task MapImageChanged(InputFileChangeEventArgs e)
    {
        MapImageChange = e.File;
        if (MapImageChange is not null)
        {
            ImagePreview = await UploadMedia(MapImageChange);
            StateHasChanged();
        }
    }

    private async Task UpdateMapImage()
    {
        if (MapImageChange is null) return;

        using var content = new MultipartFormDataContent();
        var fileContent = new StreamContent(MapImageChange.OpenReadStream(maxAllowedSize: 20480000));
        fileContent.Headers.ContentType = new MediaTypeHeaderValue(MapImageChange.ContentType);
        content.Add(fileContent, "image", MapImageChange.Name);
        var result = await (await Http.PutAsync($"api/MapsManager/image/{MapId}", content)).Content.ReadFromJsonAsync<MessageResult>();
        if (result is null) Snackbar.Add("Lỗi giao tiếp với hệ thống", Severity.Error);
        else if (!result.IsSuccess) Snackbar.Add(result.Message ?? "Lỗi chưa xác định.", Severity.Error);
        else
        {
            imageSrc = ImagePreview;
            await MapImageChangedCallBack.InvokeAsync(MapId);
            IsUpdateMapImageVisable = false;
            Snackbar.Add("Thay đổi thành công", Severity.Success);
        }
        StateHasChanged();
    }

    private async Task ExportMap()
    {
        try
        {
            if (MapId == Guid.Empty) return;
            var response = await Http.GetAsync($"api/MapExport/encrypt/{MapId}");
            if (response is not null && response.IsSuccessStatusCode)
            {
                var fileBytes = await response.Content.ReadAsByteArrayAsync();
                var fileName = response.Content.Headers.ContentDisposition?.FileName;
                using var streamRef = new DotNetStreamReference(stream: new MemoryStream(fileBytes));
                await JSRuntime.InvokeVoidAsync("DownloadMap", string.IsNullOrEmpty(fileName) ? $"{MapName}.map" : fileName, streamRef);
            }
        }
        catch (AccessTokenNotAvailableException ex)
        {
            ex.Redirect();
            return;
        }
    }
}
