using System.IO;
using System.Windows;
using System.Windows.Media;
using System.Windows.Media.Imaging;

namespace Noctalk.UI.Components.Chat;

internal static class Chat__clipboard_image_reader
{
    public static bool Try_get_clipboard_image(out BitmapSource? The_image)
    {
        The_image = null;
        IDataObject? dataObject = Clipboard.GetDataObject();
        if (dataObject is null)
        {
            return false;
        }

        foreach (string format in new[] { "PNG", "image/png" })
        {
            if (dataObject.GetDataPresent(format))
            {
                if (Try_get_bitmap_from_clipboard_data(dataObject.GetData(format), out The_image))
                {
                    return true;
                }
            }
        }

        BitmapSource? clipboardImage = Clipboard.GetImage();
        if (clipboardImage is null)
        {
            return false;
        }

        The_image = Normalize_bitmap_source(clipboardImage);
        return true;
    }

    private static bool Try_get_bitmap_from_clipboard_data(object? The_data, out BitmapSource? The_image)
    {
        The_image = null;

        if (The_data is not Stream stream)
        {
            return false;
        }

        using MemoryStream memoryStream = new();
        stream.Position = 0;
        stream.CopyTo(memoryStream);
        memoryStream.Position = 0;

        BitmapImage bitmapImage = new();
        bitmapImage.BeginInit();
        bitmapImage.CacheOption = BitmapCacheOption.OnLoad;
        bitmapImage.StreamSource = memoryStream;
        bitmapImage.EndInit();
        bitmapImage.Freeze();
        The_image = bitmapImage;
        return true;
    }

    private static BitmapSource Normalize_bitmap_source(BitmapSource The_source)
    {
        BitmapSource source = The_source;
        if (source.Format != PixelFormats.Bgra32 && source.Format != PixelFormats.Pbgra32)
        {
            source = new FormatConvertedBitmap(source, PixelFormats.Bgra32, null, 0);
        }

        source = Ensure_visible_alpha(source);

        PngBitmapEncoder encoder = new();
        encoder.Frames.Add(BitmapFrame.Create(source));
        using MemoryStream memoryStream = new();
        encoder.Save(memoryStream);
        memoryStream.Position = 0;

        BitmapImage bitmapImage = new();
        bitmapImage.BeginInit();
        bitmapImage.CacheOption = BitmapCacheOption.OnLoad;
        bitmapImage.StreamSource = memoryStream;
        bitmapImage.EndInit();
        bitmapImage.Freeze();
        return bitmapImage;
    }

    private static BitmapSource Ensure_visible_alpha(BitmapSource The_source)
    {
        int stride = The_source.PixelWidth * 4;
        byte[] pixels = new byte[stride * The_source.PixelHeight];
        The_source.CopyPixels(pixels, stride, 0);

        bool hasVisibleAlpha = false;
        bool hasColor = false;
        for (int index = 0; index < pixels.Length; index += 4)
        {
            hasVisibleAlpha |= pixels[index + 3] != 0;
            hasColor |= pixels[index] != 0 || pixels[index + 1] != 0 || pixels[index + 2] != 0;
        }

        if (hasVisibleAlpha || !hasColor)
        {
            return The_source;
        }

        for (int index = 0; index < pixels.Length; index += 4)
        {
            pixels[index + 3] = 255;
        }

        BitmapSource fixedSource = BitmapSource.Create(The_source.PixelWidth, The_source.PixelHeight, The_source.DpiX, The_source.DpiY, PixelFormats.Bgra32, null, pixels, stride);
        fixedSource.Freeze();
        return fixedSource;
    }
}
