import { BufferGeometry, BufferAttribute, MeshStandardMaterial, Mesh, DoubleSide } from "three"
import { toBuffer, IBuffer } from '../alg/mesh';
import { Vec3 } from '../math/Vec3';
import { Vec2 } from '../math/Vec2';
import { extrude, IExtrudeOptions } from '../alg/extrude';
import { Polyline } from '../struct/3d/PolyLine';
import { Polygon } from '../struct/3d/Polygon';
import { triangulation } from '../alg/trianglution';
import { flat } from '../utils/array';

export function toGeometryBuffer(vertices: number[] | Vec3[], triangles: number[], uvs: Vec2[] | number[] = []) {

    var buffer: IBuffer = toBuffer(vertices, triangles, uvs)

    var geometry = new BufferGeometry()
    geometry.setIndex(new BufferAttribute(buffer.indices, 1));
    geometry.setAttribute('position', new BufferAttribute(buffer.vertices, 3));
    geometry.setAttribute('uv', new BufferAttribute(buffer.uvs, 2));
    geometry.computeVertexNormals();

    return geometry
}

/**
 * shape 挤压后转几何体
 * @param {*} shape 
 * @param {*} arg_path 
 * @param {*} options 
 */
export function extrudeToGeometryBuffer(shape: Polygon | Polyline | Array<Vec3>, arg_path: Array<Vec3> | any, options: IExtrudeOptions) {

    var extrudeRes = extrude(shape, arg_path, options);
    return toGeometryBuffer(extrudeRes.vertices, extrudeRes.triangles, extrudeRes.uvs);
}

/**
 *  shape 挤压后转Mesh
 * @param {*} shape 
 * @param {*} arg_path 
 * @param {*} options 
 * @param {*} material 
 */
export function extrudeToMesh(shape: Polygon | Polyline | Array<Vec3>, arg_path: Array<Vec3> | any, options: IExtrudeOptions, material: any = new MeshStandardMaterial({ color: 0xeeaabb })) {
    var geometry = extrudeToGeometryBuffer(shape, arg_path, options)
    return new Mesh(geometry, material);
}


/**
 * 三角剖分后转成几何体
 * 只考虑XY平面
 * @param {*} boundary 
 * @param {*} hole 
 * @param {*} options 
 */
export function trianglutionToGeometryBuffer(boundary: any, holes: any[] = [], options: any = { normal: Vec3.UnitZ }) {
    var triangles = triangulation(boundary, holes, options)
    var vertices = [...boundary, ...flat(holes)]
    var uvs: any = [];
    vertices.reduce((acc, v) => {
        acc.push(v.x, v.y);
        return acc;
    }, uvs);

    var geometry = toGeometryBuffer(vertices, triangles, uvs);

    return geometry;
}