// Copyright 2025 the Vello Authors
// SPDX-License-Identifier: Apache-2.0 OR MIT

//! Integration benchmarks for full rendering pipelines.

use std::sync::Arc;

use criterion::Criterion;
use vello_common::kurbo::{Affine, Rect};
use vello_common::paint::{Image, ImageSource};
use vello_common::peniko::ImageSampler;
use vello_common::peniko::{Extend, ImageQuality};
use vello_common::pixmap::Pixmap;
use vello_cpu::color::AlphaColor;
use vello_cpu::{RenderContext, Resources};

/// Image scene rendering benchmark.
pub fn images(c: &mut Criterion) {
    let mut g = c.benchmark_group("images");

    let flower_image = load_flower_image();

    const VIEWPORT_WIDTH: u16 = 1280;
    const VIEWPORT_HEIGHT: u16 = 960;

    let ImageSource::Pixmap(ref image_pixmap) = flower_image else {
        panic!("Expected Pixmap");
    };
    let original_width = f64::from(image_pixmap.width());
    let original_height = f64::from(image_pixmap.height());
    let image_count = VIEWPORT_WIDTH / 256;

    g.bench_function("overlapping", |b| {
        let mut renderer = RenderContext::new(VIEWPORT_WIDTH, VIEWPORT_HEIGHT);
        let mut resources = Resources::default();
        let mut pixmap = Pixmap::new(VIEWPORT_WIDTH, VIEWPORT_HEIGHT);

        b.iter(|| {
            renderer.reset();

            for i in (1..=image_count).rev() {
                let width = 256.0 * i as f64;
                let scale = width / original_width;
                let height = original_height * scale;

                renderer.set_paint_transform(Affine::scale(scale));
                renderer.set_paint(Image {
                    image: flower_image.clone(),
                    sampler: ImageSampler {
                        x_extend: Extend::Pad,
                        y_extend: Extend::Pad,
                        quality: ImageQuality::Medium,
                        alpha: 1.0,
                    },
                });
                renderer.fill_rect(&Rect::new(0.0, 0.0, width, height));
            }

            renderer.flush();
            renderer.render(&mut pixmap, &mut resources);
            std::hint::black_box(&pixmap);
        });
    });

    g.finish();
}

fn load_flower_image() -> ImageSource {
    let image_data = include_bytes!("../../../examples/assets/splash-flower.jpg");
    let image = image::load_from_memory(image_data).expect("Failed to decode image");
    let width = image.width();
    let height = image.height();
    let rgba_data = image.into_rgba8().into_vec();

    let mut may_have_transparency = false;
    #[expect(
        clippy::cast_possible_truncation,
        reason = "Image dimensions fit in u16"
    )]
    let pixmap = Pixmap::from_parts_with_opacity(
        rgba_data
            .chunks_exact(4)
            .map(|rgba| {
                let alpha = rgba[3];
                if alpha != 255 {
                    may_have_transparency = true;
                }
                AlphaColor::from_rgba8(rgba[0], rgba[1], rgba[2], alpha)
                    .premultiply()
                    .to_rgba8()
            })
            .collect(),
        width as u16,
        height as u16,
        may_have_transparency,
    );

    ImageSource::Pixmap(Arc::new(pixmap))
}
