import { m as macro } from '../../macros2.js';
import vtkDataArray from '../../Common/Core/DataArray.js';
import { f as vtkMath } from '../../Common/Core/Math/index.js';
import vtkPolyData from '../../Common/DataModel/PolyData.js';
import vtkTriangle from '../../Common/DataModel/Triangle.js';

// ----------------------------------------------------------------------------
// vtkPolyDataNormals methods
// ----------------------------------------------------------------------------

function vtkPolyDataNormals(publicAPI, model) {
  // Set our className
  model.classHierarchy.push('vtkPolyDataNormals');
  publicAPI.vtkPolyDataNormalsExecute = (numberOfPolys, polysData, pointsData) => {
    if (!pointsData) {
      return null;
    }
    const pointNormals = new Float32Array(pointsData.length);
    const cellNormals = new Float32Array(3 * numberOfPolys);
    let cellNormalComponent = 0;
    let numberOfPoints = 0;
    const polysDataLength = polysData.length;
    const cellPointIds = [0, 0, 0];
    const cellNormal = [0, 0, 0];
    for (let c = 0; c < polysDataLength; c += numberOfPoints + 1) {
      numberOfPoints = polysData[c];
      if (numberOfPoints < 3) {
        continue; // eslint-disable-line
      }

      for (let i = 1; i <= 3; ++i) {
        cellPointIds[i - 1] = 3 * polysData[c + i];
      }
      vtkTriangle.computeNormal(pointsData.slice(cellPointIds[0], cellPointIds[0] + 3), pointsData.slice(cellPointIds[1], cellPointIds[1] + 3), pointsData.slice(cellPointIds[2], cellPointIds[2] + 3), cellNormal);
      cellNormals[cellNormalComponent++] = cellNormal[0];
      cellNormals[cellNormalComponent++] = cellNormal[1];
      cellNormals[cellNormalComponent++] = cellNormal[2];
      if (model.computePointNormals) {
        for (let i = 1; i <= numberOfPoints; ++i) {
          let pointId = 3 * polysData[c + i];
          pointNormals[pointId] += cellNormal[0];
          pointNormals[++pointId] += cellNormal[1];
          pointNormals[++pointId] += cellNormal[2];
        }
      }
    }

    // Normalize point normals.
    // A point normal is the sum of all the cell normals the point belongs to
    if (model.computePointNormals) {
      const pointNormal = [0, 0, 0];
      for (let i = 0; i < pointsData.length;) {
        pointNormal[0] = pointNormals[i];
        pointNormal[1] = pointNormals[i + 1];
        pointNormal[2] = pointNormals[i + 2];
        vtkMath.normalize(pointNormal);
        pointNormals[i++] = pointNormal[0];
        pointNormals[i++] = pointNormal[1];
        pointNormals[i++] = pointNormal[2];
      }
    }
    return [cellNormals, pointNormals];
  };
  publicAPI.requestData = (inData, outData) => {
    const numberOfInputs = publicAPI.getNumberOfInputPorts();
    if (!numberOfInputs) {
      return;
    }
    const input = inData[0];
    if (!input) {
      return;
    }
    const output = vtkPolyData.newInstance();
    output.setPoints(input.getPoints());
    output.setVerts(input.getVerts());
    output.setLines(input.getLines());
    output.setPolys(input.getPolys());
    output.setStrips(input.getStrips());
    output.getPointData().passData(input.getPointData());
    output.getCellData().passData(input.getCellData());
    output.getFieldData().passData(input.getFieldData());
    const [cellNormals, pointNormals] = publicAPI.vtkPolyDataNormalsExecute(input.getNumberOfPolys(), input.getPolys().getData(), input.getPoints().getData());
    if (model.computePointNormals) {
      const outputPointNormals = vtkDataArray.newInstance({
        numberOfComponents: 3,
        name: 'Normals',
        values: pointNormals
      });
      output.getPointData().setNormals(outputPointNormals);
    }
    if (model.computeCellNormals) {
      const outputCellNormals = vtkDataArray.newInstance({
        numberOfComponents: 3,
        name: 'Normals',
        values: cellNormals
      });
      output.getCellData().setNormals(outputCellNormals);
    }
    outData[0] = output;
  };
}

// ----------------------------------------------------------------------------
// Object factory
// ----------------------------------------------------------------------------
function defaultValues(initialValues) {
  return {
    computeCellNormals: false,
    computePointNormals: true,
    ...initialValues
  };
}

// ----------------------------------------------------------------------------
function extend(publicAPI, model) {
  let initialValues = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
  Object.assign(model, defaultValues(initialValues));

  /* Make this a VTK object */

  macro.obj(publicAPI, model);

  /* Also make it an algorithm with one input and one output */

  macro.algo(publicAPI, model, 1, 1);
  macro.setGet(publicAPI, model, ['computeCellNormals', 'computePointNormals']);

  /* Object specific methods */

  vtkPolyDataNormals(publicAPI, model);
}

// ----------------------------------------------------------------------------

const newInstance = macro.newInstance(extend, 'vtkPolyDataNormals');

// ----------------------------------------------------------------------------

var vtkPolyDataNormals$1 = {
  newInstance,
  extend
};

export { vtkPolyDataNormals$1 as default, extend, newInstance };
