using Noctalk.Shared.Chat.Constants;
using System.IO;
using System.Windows.Media;
using System.Windows.Media.Imaging;

namespace Noctalk_client.Client.Images;

public static class Image_message_processor
{
    public static byte[] Images__prepare_jpg_message(string The_image_path)
    {
        BitmapFrame sourceFrame = BitmapFrame.Create(new Uri(The_image_path), BitmapCreateOptions.IgnoreColorProfile, BitmapCacheOption.OnLoad);
        return Images__prepare_jpg_message(sourceFrame);
    }

    public static byte[] Images__prepare_jpg_message(BitmapSource The_bitmap_source)
    {
        int sourceWidth = The_bitmap_source.PixelWidth;
        int sourceHeight = The_bitmap_source.PixelHeight;
        double scale = Images__calculate_scale(sourceWidth, sourceHeight);
        BitmapSource bitmapSource = The_bitmap_source;

        if (scale < 1.0)
        {
            TransformedBitmap transformedBitmap = new(The_bitmap_source, new ScaleTransform(scale, scale));
            bitmapSource = transformedBitmap;
        }

        for (int quality = 100; quality >= 50; quality -= 5)
        {
            byte[] jpgBytes = Images__encode_jpg(bitmapSource, quality);

            if (jpgBytes.Length <= Client_constants.Max__image_message__bytes)
            {
                return jpgBytes;
            }
        }

        throw new InvalidOperationException("Image could not be compressed to <= 2 MB JPG.");
    }

    public static BitmapImage Images__bitmap_from_jpg_base64(string Message_content)
    {
        byte[] imageBytes = Convert.FromBase64String(Message_content);
        BitmapImage bitmapImage = new();
        bitmapImage.BeginInit();
        bitmapImage.CacheOption = BitmapCacheOption.OnLoad;
        bitmapImage.StreamSource = new MemoryStream(imageBytes);
        bitmapImage.EndInit();
        bitmapImage.Freeze();
        return bitmapImage;
    }

    private static double Images__calculate_scale(int The_width, int The_height)
    {
        int longSide = Math.Max(The_width, The_height);

        if (longSide <= 3000)
        {
            return 1.0;
        }

        return 3000.0 / longSide;
    }

    private static byte[] Images__encode_jpg(BitmapSource The_bitmap_source, int The_quality)
    {
        JpegBitmapEncoder encoder = new()
        {
            QualityLevel = The_quality
        };
        encoder.Frames.Add(BitmapFrame.Create(The_bitmap_source));

        using MemoryStream memoryStream = new();
        encoder.Save(memoryStream);
        return memoryStream.ToArray();
    }
}
