import {
    line3_compute_segment_point_distance_sqr
} from "../../../../../core/geom/3d/line/line3_compute_segment_point_distance_sqr.js";
import { v3_distance_sqr } from "../../../../../core/geom/vec3/v3_distance_sqr.js";
import { biplanar_edge_mapping, triplanar_corner_mapping } from "./cube_mapping.js";

/**
 *
 * @param {number} radius
 * @param {number} light_x
 * @param {number} light_y
 * @param {number} light_z
 * @param {number} outside_plane_count
 * @param {number} outside_plane_bitfield
 * @param {number[]} points
 * @return {boolean}
 */
export function detailed_sphere_frustum_intersection_test(
    radius, light_x, light_y, light_z,
    outside_plane_count, outside_plane_bitfield,
    points
) {

    const radius_sqr = radius * radius;

    if (outside_plane_count === 3) {
        // nearest point in a corner, find the corner
        const point_index = triplanar_corner_mapping[outside_plane_bitfield];

        const point_address = point_index * 3;

        const point_x = points[point_address];
        const point_y = points[point_address + 1];
        const point_z = points[point_address + 2];

        const distance_to_light_sqr = v3_distance_sqr(
            point_x, point_y, point_z,
            light_x, light_y, light_z
        );

        // query_bvh_frustum_from_objects.checks_sphere_frustum_corner++;

        // return distance_to_light_sqr <= radius_sqr;

        if (distance_to_light_sqr > radius_sqr) {

            // query_bvh_frustum_from_objects.rejection_sphere_count++;
            return false;
        }

    } else if (outside_plane_count === 2) {
        // nearest point is on an edge of two plane intersection
        const edge_bitfield = biplanar_edge_mapping[outside_plane_bitfield];

        // get 2 corners from edge bitfield
        const corner_index_0 = edge_bitfield & 0b111;
        const corner_address_0 = corner_index_0 * 3;

        const corner_index_1 = (edge_bitfield >> 3) & 0b111;
        const corner_address_1 = corner_index_1 * 3;

        const point_0_x = points[corner_address_0];
        const point_0_y = points[corner_address_0 + 1];
        const point_0_z = points[corner_address_0 + 2];

        const point_1_x = points[corner_address_1];
        const point_1_y = points[corner_address_1 + 1];
        const point_1_z = points[corner_address_1 + 2];

        const distance_to_frustum_sqr = line3_compute_segment_point_distance_sqr(
            point_0_x, point_0_y, point_0_z,
            point_1_x, point_1_y, point_1_z,
            light_x, light_y, light_z
        );

        // query_bvh_frustum_from_objects.checks_sphere_frustum_edge++;

        // return distance_to_frustum_sqr <= radius_sqr;

        if (distance_to_frustum_sqr > radius_sqr) {

            // query_bvh_frustum_from_objects.rejection_sphere_count++;
            return false;
        }
    }

    return true;
}
