import { Object3D } from "./Object3D";
import { Geometry } from "./Geometry";
import { BaseMaterial, RenderSideType } from "./materials/BaseMaterial";
import { Matrix4 } from "./math/Matrix4";
import { Ray } from "./math/Ray";
import { Sphere } from "./math/Sphere";
import { Vector3 } from "./math/Vector3";
import { Vector2 } from "./math/Vector2";
import { Raycaster, IntersectData } from "./Raycaster";

const templeSphere: Sphere = new Sphere();
const tempMatrix: Matrix4 = new Matrix4();
const tempRay: Ray = new Ray();
const tempPoint = new Vector3();

export class Mesh3D extends Object3D {
    constructor(
        public geometry: Geometry,
        public material: BaseMaterial
    ) {
        super();
    }
    _render(renderer) {
        if (!this.visible) return
        renderer.batchManager.setObjectRenderer(renderer.plugins["d3"]);
        renderer.plugins["d3"].render(this)
    }

    raycast(raycaster: Raycaster, intersects: IntersectData[]) {
        if (!this.visible || !this.geometry || !this.material || this.material.wireframe) return;
        var geometry = this.geometry;
        var matrixWorld = this._worldMatrix;

        // Checking boundingSphere distance to ray

        if (!geometry.boundingSphere) geometry.computeBoundingSphere();

        templeSphere.copy(geometry.boundingSphere);
        templeSphere.applyMatrix4(matrixWorld);

        if (raycaster.ray.intersectsSphere(templeSphere) === false) return;

        //

        tempMatrix.setInverseOf(matrixWorld);
        tempRay.copy(raycaster.ray).applyMatrix4(tempMatrix);
        // Check boundingBox before continuing
        if (geometry.boundingBox !== null && tempRay.intersectsBox(geometry.boundingBox) === false) return;

        var intersection: IntersectData;

        var a = new Vector3(), b = new Vector3(), c = new Vector3();
        var index = geometry._indices;
        var position = geometry._vertices;

        if (index) {
            for (var i = 0; i < index.length; i += 3) {
                a.set(position[i * 3], position[i * 3 + 1], position[i * 3 + 2]);
                b.set(position[(i + 1) * 3], position[(i + 1) * 3 + 1], position[(i + 1) * 3 + 2]);
                c.set(position[(i + 2) * 3], position[(i + 2) * 3 + 1], position[(i + 2) * 3 + 2]);

                intersection = checkIntersection(
                    this,
                    raycaster,
                    tempRay,
                    a,
                    b,
                    c,
                    tempPoint
                );
                if (intersection) {//有一个就出
                    intersects.push(intersection);
                    break;
                }
            }
        }
        else if (position) {
            for (var i = 0; i < position.length; i += 9) {
                a.set(position[i * 3], position[i * 3 + 1], position[i * 3 + 2]);
                b.set(position[(i + 1) * 3], position[(i + 1) * 3 + 1], position[(i + 1) * 3 + 2]);
                c.set(position[(i + 2) * 3], position[(i + 2) * 3 + 1], position[(i + 2) * 3 + 2]);

                intersection = checkIntersection(
                    this,
                    raycaster,
                    tempRay,
                    a,
                    b,
                    c,
                    tempPoint
                );
                if (intersection) {//有一个就出
                    intersects.push(intersection);
                    break;
                }
            }
        }
    };
}



var intersectionPointWorld = new Vector3();
function checkIntersection(
    object: Mesh3D,
    raycaster: Raycaster,
    ray: Ray,
    pA: Vector3,
    pB: Vector3,
    pC: Vector3,
    point: Vector3
): IntersectData {
    var material = object.material
    var intersect: Vector3 | null;
    if (material.side === RenderSideType.BackSide) {
        intersect = ray.intersectTriangle(pC, pB, pA, true, point);
    } else {
        intersect = ray.intersectTriangle(pA, pB, pC, material.side !== RenderSideType.DoubleSide, point);
    }
    if (intersect === null) return null;

    intersectionPointWorld.copy(point);
    intersectionPointWorld.applyMatrix4(object._worldMatrix);
    var distance = raycaster.ray.origin.distanceTo(intersectionPointWorld);
    if (distance < raycaster.near || distance > raycaster.far) return null;
    return {
        distance: distance,
        point: intersectionPointWorld.clone(),
        object: object
    };
}
//交付分
var a = 5
//时间分每天
var b = 1
//极限时间
var j = 15
//项目基础时间
var i = 4

function aaa(t) {
    t -= i
    return a + t * b + (t * t) / j * a / i / i;
}

function bbb(t) {
    //完整项目按4天
    t -= i
    return a + t * b + (t * t) / j * a / i / i;
}