using System;
using System.IO;
using System.Text.Json;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using Microsoft.Web.WebView2.Core;

namespace DansoriEQ.App.Controls;

public partial class Live2DCharacterView : UserControl
{
    private const string AssetsHostName = "dansori-assets.local";
    private bool _hostReady;

    public Live2DCharacterView()
    {
        InitializeComponent();
        Loaded += async (_, _) => await InitializeAsync();
    }

    public async Task InitializeAsync()
    {
        try
        {
            var assetsRoot = Path.Combine(AppContext.BaseDirectory, "Assets");
            var hostPath = Path.Combine(assetsRoot, "Live2DHost", "index.html");
            if (!File.Exists(hostPath))
            {
                FallbackText.Text = "host file missing";
                return;
            }

            await CharacterWebView.EnsureCoreWebView2Async();
            CharacterWebView.CoreWebView2.WebMessageReceived -= OnWebMessageReceived;
            CharacterWebView.CoreWebView2.WebMessageReceived += OnWebMessageReceived;
            CharacterWebView.CoreWebView2.SetVirtualHostNameToFolderMapping(
                AssetsHostName,
                assetsRoot,
                CoreWebView2HostResourceAccessKind.Allow);

            var cacheBust = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
            CharacterWebView.Source = new Uri($"https://{AssetsHostName}/Live2DHost/index.html?v={cacheBust}");
            FallbackText.Text = "loading host";
        }
        catch (Exception ex)
        {
            FallbackText.Text = ex.Message;
        }
    }

    public void SetState(string state)
        => Post(new { type = "setState", state });

    public void SetCharacter(string characterId)
        => Post(new { type = "setCharacter", characterId });

    public void ShowText(string message)
        => Post(new { type = "showText", message });

    private void Post(object payload)
    {
        if (!_hostReady || CharacterWebView.CoreWebView2 is null) return;
        CharacterWebView.CoreWebView2.PostWebMessageAsJson(JsonSerializer.Serialize(payload));
    }

    private void OnWebMessageReceived(object? sender, CoreWebView2WebMessageReceivedEventArgs e)
        => OnWebMessage(e.WebMessageAsJson);

    private void OnWebMessage(string json)
    {
        try
        {
            using var doc = JsonDocument.Parse(json);
            var root = doc.RootElement;
            if (root.TryGetProperty("type", out var type) && type.GetString() == "hostReady")
            {
                _hostReady = true;
                Fallback.Visibility = Visibility.Collapsed;
                SetCharacter("leesori");
                SetState("idle");
            }
        }
        catch
        {
            // Ignore malformed messages from the local host page.
        }
    }
}
