import * as THREE from '../node_modules/three/src/Three';
import { color } from './shared'
export function extrude(sketch, depth) {

  let constraints = sketch.constraints;
  let linkedObjs = sketch.linkedObjs;
  let children = sketch.obj3d.children;
  let objIdx = sketch.objIdx;
  let visited = new Set()
  let v2s = []

  function findPair(node) {
    if (node.userData.construction) return;
    visited.add(node)
    let linkedObj = linkedObjs.get(node.userData.l_id)
    let arr;

    let lineNode
    if (linkedObj[0] == 'line') {
      lineNode = linkedObj[1][2]
    } else if (linkedObj[0] == 'arc') {
      lineNode = linkedObj[1][3]
    }

    arr = children[objIdx.get(lineNode)].geometry.attributes.position.array
    let nextIdx
    if (linkedObj[1][0] == node.name) {
      nextIdx = 1
      for (let i = 0; i < arr.length; i += 3) {
        v2s.push(new THREE.Vector2(arr[i], arr[i + 1]))
      }
    } else {
      nextIdx = 0
      for (let i = arr.length - 3; i >= 0; i -= 3) {
        v2s.push(new THREE.Vector2(arr[i], arr[i + 1]))
      }
    }

    let d = children[
      objIdx.get(
        linkedObj[1][nextIdx]
      )
    ]
    if (d == children[sketch.geomStartIdx + 1]) {
      // console.log('pair found')
    };
    findTouching(d)

  }


  function findTouching(node) {
    // console.log(node.name, 'yy')
    for (let t of node.userData.constraints) {
      // console.log(constraints.get(t)[2], node.name)
      if (constraints.get(t)[0] != 'points_coincident') continue
      for (let c of constraints.get(t)[2]) {
        if (c == -1) continue;
        const d = children[objIdx.get(c)]
        if (d == node) continue;
        if (d == children[sketch.geomStartIdx + 1]) {
          // console.log('loop found')
        } else {
          // if (!visited.has(d)) {
          findPair(d)
          // }
        };
      }
    }
  }


  findPair(children[sketch.geomStartIdx + 1]) // ?? possibly allow user select search start point

  const shape = new THREE.Shape(v2s);
  // const extrudeSettings = { depth: Math.abs(depth), bevelEnabled: false };
  const extrudeSettings = { depth, bevelEnabled: false };


  const geometry = new THREE.ExtrudeGeometry(shape, extrudeSettings);

  const material = new THREE.MeshPhongMaterial({
    color: color.mesh,
    emissive: color.emissive,
    // wireframe:true
  });

  const mesh = new THREE.Mesh(geometry, material)



  mesh.userData.type = 'mesh'
  mesh.userData.featureInfo = [sketch.obj3d.name, depth]
  mesh.layers.enable(1)

  // const vertices = new THREE.Points(mesh.geometry, new THREE.PointsMaterial({ size: 0 }));
  const vertices = new THREE.Points(mesh.geometry, new THREE.PointsMaterial());
  vertices.userData.type = 'point'
  vertices.visible = false
  vertices.layers.enable(1)

  mesh.add(vertices)

  mesh.matrixAutoUpdate = false;
  mesh.matrix.multiply(sketch.obj3d.matrix)

  if (depth < 0) {
    flipBufferGeometryNormals(mesh.geometry)
    mesh.userData.inverted = true
    // console.log('heere')
    console.log('heere', mesh)
  }

  return mesh


}


export function flipBufferGeometryNormals(geometry) {
  //https://stackoverflow.com/a/54496265
  const tempXYZ = [0, 0, 0];

  // flip normals
  for (let i = 0; i < geometry.attributes.normal.array.length / 9; i++) {
    // cache a coordinates
    tempXYZ[0] = geometry.attributes.normal.array[i * 9];
    tempXYZ[1] = geometry.attributes.normal.array[i * 9 + 1];
    tempXYZ[2] = geometry.attributes.normal.array[i * 9 + 2];

    // overwrite a with c
    geometry.attributes.normal.array[i * 9] =
      geometry.attributes.normal.array[i * 9 + 6];
    geometry.attributes.normal.array[i * 9 + 1] =
      geometry.attributes.normal.array[i * 9 + 7];
    geometry.attributes.normal.array[i * 9 + 2] =
      geometry.attributes.normal.array[i * 9 + 8];

    // overwrite c with stored a values
    geometry.attributes.normal.array[i * 9 + 6] = tempXYZ[0];
    geometry.attributes.normal.array[i * 9 + 7] = tempXYZ[1];
    geometry.attributes.normal.array[i * 9 + 8] = tempXYZ[2];
  }

  // change face winding order
  for (let i = 0; i < geometry.attributes.position.array.length / 9; i++) {
    // cache a coordinates
    tempXYZ[0] = geometry.attributes.position.array[i * 9];
    tempXYZ[1] = geometry.attributes.position.array[i * 9 + 1];
    tempXYZ[2] = geometry.attributes.position.array[i * 9 + 2];

    // overwrite a with c
    geometry.attributes.position.array[i * 9] =
      geometry.attributes.position.array[i * 9 + 6];
    geometry.attributes.position.array[i * 9 + 1] =
      geometry.attributes.position.array[i * 9 + 7];
    geometry.attributes.position.array[i * 9 + 2] =
      geometry.attributes.position.array[i * 9 + 8];

    // overwrite c with stored a values
    geometry.attributes.position.array[i * 9 + 6] = tempXYZ[0];
    geometry.attributes.position.array[i * 9 + 7] = tempXYZ[1];
    geometry.attributes.position.array[i * 9 + 8] = tempXYZ[2];
  }

  // flip UV coordinates
  for (let i = 0; i < geometry.attributes.uv.array.length / 6; i++) {
    // cache a coordinates
    tempXYZ[0] = geometry.attributes.uv.array[i * 6];
    tempXYZ[1] = geometry.attributes.uv.array[i * 6 + 1];

    // overwrite a with c
    geometry.attributes.uv.array[i * 6] =
      geometry.attributes.uv.array[i * 6 + 4];
    geometry.attributes.uv.array[i * 6 + 1] =
      geometry.attributes.uv.array[i * 6 + 5];

    // overwrite c with stored a values
    geometry.attributes.uv.array[i * 6 + 4] = tempXYZ[0];
    geometry.attributes.uv.array[i * 6 + 5] = tempXYZ[1];
  }

  geometry.attributes.normal.needsUpdate = true;
  geometry.attributes.position.needsUpdate = true;
  geometry.attributes.uv.needsUpdate = true;
}


