import { query_vertex_is_boundary } from "../query/query_vertex_is_boundary.js";
import { compute_face_normal_change_dot_product } from "./compute_face_normal_change_dot_product.js";
import { compute_edge_collapse_cost_quadratic } from "./quadratic/compute_edge_collapse_cost_quadratic.js";

/**
 * Value to be used when collapse would flip normal of one or more adjacent faces
 * @type {number}
 */
const INVALID_FLIP_COST = Number.MAX_VALUE;

/**
 * Approximate cost of collapsing an edge, removing victim vertex from topology and merging it with the target vertex
 * NOTE: adapted from THREE.js mesh simplification code
 * @param {TopoVertex} victim
 * @param {TopoVertex} target
 * @param {TopoEdge} victim_edge
 * @param {Map<number, Quadric3>} vertex_quadratics
 * @return {number}
 */
export function computeEdgeCollapseCost(victim, target, victim_edge, vertex_quadratics) {
    // console.warn('+computeEdgeCollapseCost');

    // if we collapse edge uv by moving u to v then how
    // much different will the model change, i.e. the "error".

    const edge_length = victim_edge.lengthSqr;
    let curvature = 0;

    let normal_cost = 0;

    // find the "sides" triangles that are on the edge uv
    const side_faces = victim_edge.faces;
    const side_face_count = side_faces.length;


    // use the triangle facing most away from the sides
    // to determine our curvature term
    const victim_faces = victim.faces;
    const victim_face_count = victim_faces.length;

    let fixed_cost = 0;

    for (let i = 0; i < victim_face_count; i++) {
        const face = victim_faces[i];

        // check if face normal would be flipped by the operation, this is very undesirable
        const face_normal_change = compute_face_normal_change_dot_product(face, victim, target);

        if (face_normal_change < 0) {
            // normal change beyond 90deg, increase the cost significantly
            return INVALID_FLIP_COST;
        }

    }

    const quadratic_cost = compute_edge_collapse_cost_quadratic(victim, target, target, vertex_quadratics);

    if (side_face_count < 2) {

        // we add some arbitrary cost for borders,
        curvature = 1;

        fixed_cost += 1;
    }


    if (query_vertex_is_boundary(victim)) {
        // prefer not to erase border vertices to preserve shape
        curvature += 1;

        fixed_cost += 1;
    }

    const amt = quadratic_cost + edge_length * (curvature + normal_cost) + fixed_cost;

    // console.warn(`edge_length:${edge_length}, curvature:${curvature}, normal_cost:${normal_cost}`);

    // console.warn('-computeEdgeCollapseCost');

    return amt;

}
