///////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2002-2025, Open Design Alliance (the "Alliance").
// All rights reserved.
//
// This software and its documentation and related materials are owned by
// the Alliance. The software may only be incorporated into application
// programs owned by members of the Alliance, subject to a signed
// Membership Agreement and Supplemental Software License Agreement with the
// Alliance. The structure and organization of this software are the valuable
// trade secrets of the Alliance and its suppliers. The software is also
// protected by copyright law and international treaty provisions. Application
// programs incorporating this software must include the following statement
// with their copyright notices:
//
//   This application incorporates Open Design Alliance software pursuant to a
//   license agreement with Open Design Alliance.
//   Open Design Alliance Copyright (C) 2002-2025 by Open Design Alliance.
//   All rights reserved.
//
// By use of this software, its documentation or related materials, you
// acknowledge and accept the above terms.
///////////////////////////////////////////////////////////////////////////////

import { LineSegmentsGeometry } from "three/examples/jsm/lines/LineSegmentsGeometry.js";

export class HighlighterUtils {
  static isBreak(positions: Float32Array, i: number) {
    return (
      isNaN(positions[i]) ||
      isNaN(positions[i + 1]) ||
      isNaN(positions[i + 2]) ||
      positions[i] === Infinity ||
      positions[i] === -Infinity ||
      positions[i + 1] === Infinity ||
      positions[i + 1] === -Infinity ||
      positions[i + 2] === Infinity ||
      positions[i + 2] === -Infinity
    );
  }

  static fromIndexedLine(positions: Float32Array, indices: number[]) {
    const lineGeometry = new LineSegmentsGeometry();
    const segments = [];

    for (let i = 0; i < indices.length; i += 2) {
      const idx1 = indices[i] * 3;
      const idx2 = indices[i + 1] * 3;

      if (indices[i] === -1 || indices[i + 1] === -1) {
        continue;
      }

      segments.push(
        positions[idx1],
        positions[idx1 + 1],
        positions[idx1 + 2],
        positions[idx2],
        positions[idx2 + 1],
        positions[idx2 + 2]
      );
    }

    if (segments.length === 0) return null;

    lineGeometry.setPositions(segments);
    return lineGeometry;
  }

  static fromNonIndexedLine(positions: Float32Array, isLineSegments: boolean) {
    const lineGeometry = new LineSegmentsGeometry();
    const segments = [];

    if (isLineSegments) {
      for (let i = 0; i < positions.length; i += 6) {
        if (i + 5 >= positions.length) break;

        if (HighlighterUtils.isBreak(positions, i) || HighlighterUtils.isBreak(positions, i + 3)) continue;

        segments.push(
          positions[i],
          positions[i + 1],
          positions[i + 2],
          positions[i + 3],
          positions[i + 4],
          positions[i + 5]
        );
      }
    } else {
      let lastValidIndex = -1;

      for (let i = 0; i < positions.length; i += 3) {
        if (HighlighterUtils.isBreak(positions, i)) {
          lastValidIndex = -1;
          continue;
        }

        if (lastValidIndex !== -1) {
          segments.push(
            positions[lastValidIndex],
            positions[lastValidIndex + 1],
            positions[lastValidIndex + 2],
            positions[i],
            positions[i + 1],
            positions[i + 2]
          );
        }
        lastValidIndex = i;
      }
    }

    if (segments.length === 0) return null;

    lineGeometry.setPositions(segments);
    return lineGeometry;
  }
}
