//

import { assert } from "../../../../../core/assert.js";
import { max2 } from "../../../../../core/math/max2.js";
import { renderSamplerFromTexture } from "../../../render/visibility/hiz/buildCanvasViewFromTexture.js";
import { Sampler2D } from "../../../texture/sampler/Sampler2D.js";
import { sampler2d_build_cutout } from "./sampler2d_build_cutout.js";

/**
 * TODO For this specific use-case with octahedral impostors we can get away tracing a circular shape in general.
 *      A circle is a lot easier to quantize (as long as we make sure we place edges outside of the circle)
 * @param {ImpostorDescription} impostor
 * @param {THREE.WebGLRenderer} renderer
 * @param {number} vertex_limit how many vertices to use for the billboard, more vertices will provide better fit and lower area reducing overdraw at the cost of extra triangles. Prefer values between 4 and 16
 * @returns {Float32Array}
 */
export function build_cutout_from_atlas_by_alpha({

                                                     impostor,
                                                     renderer,
                                                     vertex_limit = 8
                                                 }) {

    assert.isNonNegativeInteger(vertex_limit, 'vertex_limit');
    assert.greaterThanOrEqual(vertex_limit, 3);

    assert.defined(renderer, 'renderer');

    // get impostor data first

    const ctrl = renderSamplerFromTexture({
        renderer: renderer,
        // swizzle: ['a', 'a', 'a', 1],
        swizzle: ['a', 'a', 'a', 1],
        texture: impostor.rt.texture[0]
    });

    ctrl.render();

    const source_canvas_data = ctrl.destination.data;

    // build set of border pixels
    const frame_size = impostor.resolution / impostor.frame_count;
    const frame_size_i = Math.ceil(frame_size);

    const accumulator = Sampler2D.uint8(1, frame_size_i, frame_size_i);

    for (let i = 0; i < impostor.frame_count; i++) {

        const frame_offset_y = Math.floor(frame_size * i);

        for (let j = 0; j < impostor.frame_count; j++) {

            const frame_offset_x = Math.floor(frame_size * j);

            for (let y = 0; y < frame_size_i; y++) {
                const global_y = frame_offset_y + y;

                for (let x = 0; x < frame_size_i; x++) {

                    const global_x = x + frame_offset_x;

                    const global_index = global_y * impostor.resolution + global_x;

                    const v = source_canvas_data[global_index * 4];


                    if (v > 0) {

                        const local_index = y * frame_size_i + x;

                        accumulator.data[local_index] = max2(v, accumulator.data[local_index]);
                    }
                }
            }
        }
    }

    const cutout_points = sampler2d_build_cutout(accumulator, vertex_limit, frame_size);

    // normalize points
    for (let i = 0; i < vertex_limit; i++) {
        cutout_points[i * 2] /= frame_size;
        cutout_points[i * 2 + 1] /= frame_size;
    }


    return cutout_points;
}
