using System.Windows;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using Engine.Asset;
using Engine.Graphics;
using Engine.Graphics.Pixel;
using Engine.Graphics.Texture;
using OpenTK.Windowing.Common;
using CancelEventArgs = System.ComponentModel.CancelEventArgs;

namespace PresenterWpf;

public partial class MainWindow : Window, IPresenter
{
  public bool IsExiting { get; private set; }
  public new int Width { get; private set; }
  public new int Height { get; private set; }

  private bool _scheduledResize;

  public event Action<ResizeEventArgs>? Resize;

  private readonly Engine.Engine _engine;
  private Image<Rgb8>? _image;
  private WriteableBitmap? _bitmap;

  public MainWindow(Engine.Engine parEngine)
  {
    InitializeComponent();

    _engine = parEngine;
  }

  public void Update(double parDeltaTime)
  {
    Dispatcher.Invoke(() =>
    {
      if ((int)Image.ActualWidth != Width || (int)Image.ActualHeight != Height)
      {
        Width = (int)Image.ActualWidth;
        Height = (int)Image.ActualHeight;

        _scheduledResize = true;
      }
    });
  }

  public void Render()
  {
    if (_scheduledResize)
    {
      _scheduledResize = false;
      Resize?.Invoke(new ResizeEventArgs(Width, Height));
    }
  }

  public void Present(IConstTexture parTexture)
  {
    if (_image == null || parTexture.Width != _image.Width || parTexture.Height != _image.Height)
    {
      _image = new Image<Rgb8>(parTexture.Width, parTexture.Height);
    }

    parTexture.ReadPixels(_image);
    Dispatcher.Invoke(() =>
    {
      if (_bitmap == null || _bitmap.PixelWidth != _image.Width || _bitmap.PixelHeight != _image.Height)
      {
        _bitmap = new WriteableBitmap(_image.Width, _image.Height, 96, 96, PixelFormats.Rgb24, null);
      }

      DrawImage(_image);
      Image.Source = _bitmap;
    });
  }

  public void Exit()
  {
    Dispatcher.Invoke(Close);
  }

  private void DrawImage(Image<Rgb8> parImage)
  {
    try
    {
      _bitmap!.Lock();
      _bitmap!.WritePixels(new Int32Rect(0, 0, parImage.Width, parImage.Height), parImage.Pixels, parImage.Width * 3, 0,
        0);
    }
    finally
    {
      _bitmap!.Unlock();
    }
  }

  private void MainWindow_OnClosing(object? parSender, CancelEventArgs parE)
  {
    IsExiting = true;
  }
}