import { assert } from "../../../../core/assert.js";
import { GROUP_WITH_ANY } from "./constants/GROUP_WITH_ANY.js";
import { ORIENT_PRESERVING } from "./constants/ORIENT_PRESERVING.js";
import { AddTriToGroup } from "./AddTriToGroup.js";

/**
 *
 * @param {number[]} piTriListIn
 * @param {STriInfo[]} psTriInfos
 * @param {number} iMyTriIndex
 * @param {SGroup} pGroup
 * @return {boolean}
 */
export function AssignRecur(
    piTriListIn,
    psTriInfos,
    iMyTriIndex,
    pGroup
) {

    // track down vertex
    const iVertRep = pGroup.iVertexRepresentitive;
    const triangle_address = iMyTriIndex * 3;

    let i = -1;

    if (piTriListIn[triangle_address] === iVertRep) {
        i = 0;
    } else if (piTriListIn[triangle_address + 1] === iVertRep) {
        i = 1;
    } else if (piTriListIn[triangle_address + 2] === iVertRep) {
        i = 2;
    }

    assert.greaterThanOrEqual(i, 0);
    assert.lessThan(i, 3);

    const pMyTriInfo = psTriInfos[iMyTriIndex];

    // early out
    const sGroups = pMyTriInfo.AssignedGroup;

    if (sGroups[i] === pGroup) {
        return true;
    } else if (sGroups[i] !== null) {
        return false;
    }

    if ((pMyTriInfo.iFlag & GROUP_WITH_ANY) !== 0) {
        // first to group with a group-with-anything triangle
        // determines its orientation.
        // This is the only existing order dependency in the code!!
        if (
            sGroups[0] === null &&
            sGroups[1] === null &&
            sGroups[2] === null
        ) {
            pMyTriInfo.iFlag &= (~ORIENT_PRESERVING);
            pMyTriInfo.iFlag |= (pGroup.bOrientPreservering ? ORIENT_PRESERVING : 0);
        }
    }

    const bOrient = (pMyTriInfo.iFlag & ORIENT_PRESERVING) !== 0;

    if (bOrient !== pGroup.bOrientPreservering) {
        return false;
    }

    AddTriToGroup(pGroup, iMyTriIndex);
    sGroups[i] = pGroup;

    const neigh_indexL = pMyTriInfo.FaceNeighbors[i];
    const neigh_indexR = pMyTriInfo.FaceNeighbors[i > 0 ? (i - 1) : 2];

    if (neigh_indexL >= 0) {
        AssignRecur(piTriListIn, psTriInfos, neigh_indexL, pGroup);
    }
    if (neigh_indexR >= 0) {
        AssignRecur(piTriListIn, psTriInfos, neigh_indexR, pGroup);
    }


    return true;
}
