var ClipPlaneManager = {
    clipMeshInfos: [],
    activeMeshInfo: undefined,
    anyMeshIsActive: false,
    refreshClipPlanesMesh: function (imagePath) {
        this.clipMeshInfos.forEach(clipMeshInfo => {
            if (clipMeshInfo.Index != undefined) return;
            LoaderUtility.loadUniqueTexture(imagePath + "//" + clipMeshInfo.ImageName,
                function (texture) {
                    clipMeshInfo.Object.material.map.dispose();
                    clipMeshInfo.Object.material.map = texture;
                    clipMeshInfo.Object.material.needsUpdate = true;
                });
        });
    },
    //通过三点生成切面 
    generateClipPlaneByPoints: function (points, callback) {
        if (points.length < 3)
            return false;
        this.resetClipInfo();
        //生成切面
        let clipPlane = new THREE.Plane();
        clipPlane.setFromCoplanarPoints(points[0], points[1], points[2]);
        //根据cube中心点判断切面的方向
        let zero = new THREE.Vector3(0, 0, 0);
        cube.localToWorld(zero);

        let cubeVector = points[0].clone().sub(zero);
        let direction = cubeVector.dot(clipPlane.normal);
        if (direction > 0) {
            clipPlane.normal.negate();
            clipPlane.constant = -clipPlane.constant;
            //cube中心点为（width/2，height/2，depth/2）
            //切面在中心点左侧，留cube右半部分，故相机位置在cube中心点左侧，相机距cube中心点距离 width *（2+1/2）
            camera.position.set(-width * 2, height / 2, depth / 2);
        }
        else {
            //切面在中心点右侧，留cube左半部分，故相机位置在cube中心点右侧，相机距cube中心点距离 width *（3-1/2）
            camera.position.set(width * 3, height / 2, depth / 2);
        }
        orbitCtl.update();

        //生成切面对应的mesh
        let mesh = new THREE.Mesh(new THREE.PlaneGeometry(), new THREE.MeshPhongMaterial({ side: THREE.FrontSide, map: new THREE.Texture(), clippingPlanes: [] }));
        scene.add(mesh);
        //添加切面信息
        let clipMeshInfo = ClipMeshInfo.createNew(mesh, clipPlane);
        this.addClipMeshInfo(clipMeshInfo);
        this.activeMeshInfo = ActiveMeshInfo.createNew(clipMeshInfo, zero, MeshType.additionalMesh);
        refreshClipMesh(clipPlane, mesh, clipMeshInfo.ImageName,
            function () {
                if (SpriteManager.clipType == ClipType.MoveClipPlane) {
                    addRotateInfo();
                }
                if (callback != undefined) {
                    callback();
                }
            });
        return true;
    },
    //通过切割线生成切面 
    generateClipPlane: function () {
        if(!LinesDrawingManager.clipLine.visible)
        {
            return;
        }

        let endPoint = LinesDrawingManager.clipLine.geometry.userData;
        let normal = this.activeMeshInfo.getClonedNormal();
        let startPoint = this.activeMeshInfo.Point;
        if (startPoint.distanceTo(endPoint) == 0)
            return;
        let clipLine = startPoint.clone().sub(endPoint);
        let normalVector = new THREE.Vector3();
        normalVector.crossVectors(clipLine, normal).normalize();
        //根据cube中心点判断切面的方向
        let zero = new THREE.Vector3(0, 0, 0);
        cube.localToWorld(zero);
        let cubeVector = startPoint.clone().sub(zero);
        if (cubeVector.dot(normalVector) > 0) {
            normalVector.negate();
        }
        //生成切面
        let clipPlane = new THREE.Plane();
        clipPlane.setFromNormalAndCoplanarPoint(normalVector, endPoint);
        //移除现有切面中无用的切面
        this.removeUselessClipPlane(clipPlane);
        //生成切面对应的mesh
        let mesh = new THREE.Mesh(new THREE.PlaneGeometry(), new THREE.MeshPhongMaterial({ side: THREE.FrontSide, map: new THREE.Texture(), clippingPlanes: [] }));
        scene.add(mesh);
        //添加切面信息
        let clipMeshInfo = ClipMeshInfo.createNew(mesh, clipPlane);
        this.addClipMeshInfo(clipMeshInfo);
        refreshClipMesh(clipPlane, mesh, clipMeshInfo.ImageName);
        LinesDrawingManager.hideClipLine();
    },
    //通过cube表面切面
    generateCubeFaceClipPlane: function () {
        let clipMeshInfo = undefined;
        //计算切面信息（normal，distance）
        let normal = this.activeMeshInfo.getClonedNormal().negate();
        // zero to face's first point.
        let faceVector = cube.localToWorld(this.activeMeshInfo.Mesh.object.geometry.vertices[this.activeMeshInfo.Mesh.face.a].clone());
        let distance = Math.abs(faceVector.dot(normal)) + 5;
        //判断切面是否已存在
        if (this.clipMeshInfos.length > 0) {
            clipMeshInfo = this.clipMeshInfos.find(m => m.Plane.normal.equals(normal) && m.Plane.constant == distance);
        }
        if (clipMeshInfo == undefined) {
            //生成切面对应的mesh
            let material = cube.material[this.activeMeshInfo.Mesh.face.materialIndex].clone();
            material.clippingPlanes = [];
            let mesh = new THREE.Mesh(new THREE.PlaneGeometry(), material);
            scene.add(mesh);
            //生成切面
            let faceClipPlane = new THREE.Plane(normal, distance);
            //添加切面信息
            clipMeshInfo = ClipMeshInfo.createNew(mesh, faceClipPlane, this.activeMeshInfo.Mesh.face.materialIndex);
            this.addClipMeshInfo(clipMeshInfo);    
        }

        this.activeMeshInfo.Mesh = clipMeshInfo;
        this.activeMeshInfo.MeshType = MeshType.additionalMesh;
    },
    //移除切面数组里指定位置的元素，若index未定义则移除最后一个元素
    removeClipPlane: function (index) {
        if (index == undefined) {
            index = this.clipMeshInfos.length - 1;
            this.resetActiveMeshInfo();       
        }
        if (index < 0)
            return;
        if (this.clipMeshInfos.length <= 0)
            return;
        let clipPlane = this.clipMeshInfos[index].Plane;
        cube.material.forEach(material => {
            ClipPlaneManager.removeMaterialClipPlane(material.clippingPlanes, clipPlane);
        });
        this.clipMeshInfos.forEach(m => {
            if (m.Object.material.clippingPlanes.length > 0) {
                ClipPlaneManager.removeMaterialClipPlane(m.Object.material.clippingPlanes, clipPlane);
            }
        });
        scene.remove(this.clipMeshInfos[index].Object);
        // jsObj.DeleteClipImageData(this.clipMeshInfos[index].ImageName);
        Dart_GetStringData(this.clipMeshInfos[index].ImageName);
        this.clipMeshInfos[index].dispose();
        this.clipMeshInfos.splice(index, 1);

    },
    //排序：将最后激活的切面移到切面列表的最后
    moveElementToEnd: function (clipMeshInfo) {
        let index = this.clipMeshInfos.findIndex(n => n.Object == clipMeshInfo.Object && n.Plane == clipMeshInfo.Plane);
        this.clipMeshInfos.splice(index, 1);
        this.clipMeshInfos.push(clipMeshInfo);

    },
    //获取鼠标点击时激活的面信息
    getActiveMeshInfo: function (raycaster) {        
        let intersects = raycaster.intersectObject(cube);
        if (intersects.length <= 0) {
            //not intersect cube
            return undefined;
        }
        if (this.clipMeshInfos.length > 0) {
            let distance = 0;
            let intersectMesh = undefined;
            let clipMeshInfo = undefined;
            this.clipMeshInfos.forEach(m => {
                let meshIntersectObject = raycaster.intersectObject(m.Object);
                //取鼠标最远拾取的mesh
                if (meshIntersectObject.length > 0) {
                    if (distance < meshIntersectObject[0].distance) {
                        intersectMesh = meshIntersectObject[0];
                        clipMeshInfo = m;
                        distance = meshIntersectObject[0].distance;
                    }
                }

            });
            if (distance > 0) {
                return ActiveMeshInfo.createNew(clipMeshInfo, intersectMesh.point, MeshType.additionalMesh);
            }
        }   
        return ActiveMeshInfo.createNew(intersects[0], intersects[0].point, MeshType.cube);
    },
    //获取激活面的边框线
    getActiveMeshBorders: function () {
        let meshBorders = [];
        if (this.activeMeshInfo.Vertices.length > 1) {
            for (let cursor = 0; cursor < this.activeMeshInfo.Vertices.length - 1; cursor++) {
                meshBorders.push(new THREE.Line3(this.activeMeshInfo.Vertices[cursor], this.activeMeshInfo.Vertices[cursor + 1]));
            }
        }
        return meshBorders;
    },
    //获取使用同一转轴的相邻面（非激活面）的法向量
    getNeighbourPlaneNormal: function (line, clipMeshInfo) {

        //查找包含旋转轴line的切面法向量
        let projectStartPoint = new THREE.Vector3();
        let projectEndPoint = new THREE.Vector3();
        let clippingPlanes = clipMeshInfo.Object.material.clippingPlanes;
        if (clippingPlanes != undefined && clippingPlanes.length > 0) {
            for (let cursor = 0; cursor < clippingPlanes.length; cursor++) {
                clippingPlanes[cursor].projectPoint(line.start, projectStartPoint);
                clippingPlanes[cursor].projectPoint(line.end, projectEndPoint);
                if (line.start.distanceTo(projectStartPoint) < Accuracy && line.end.distanceTo(projectEndPoint) < Accuracy) {
                    return clippingPlanes[cursor].normal;
                }
            }
        }

        //查找包含旋转轴line的cube face法向量
        //判断旋转轴是否在cube的左/右面上且cubeFace在旋转范围内
        if (this.isLineInCubeFaceByFaceNormal(line, CubeFaceNormalHelper.Left)
            && this.isWithinRotateRange(CubeFaceNormalHelper.Left, clipMeshInfo.Plane.normal)) {
            return CubeFaceNormalHelper.Left;
        }

        //判断旋转轴是否在cube的前/后面上且cubeFace在旋转范围内
        if (this.isLineInCubeFaceByFaceNormal(line, CubeFaceNormalHelper.Front)
            && this.isWithinRotateRange(CubeFaceNormalHelper.Front, clipMeshInfo.Plane.normal)) {
            return CubeFaceNormalHelper.Front;
        }

        //判断旋转轴是否在cube的上/下面上且cubeFace在旋转范围内
        if (this.isLineInCubeFaceByFaceNormal(line, CubeFaceNormalHelper.Down)
            && this.isWithinRotateRange(CubeFaceNormalHelper.Down, clipMeshInfo.Plane.normal)) {
            return CubeFaceNormalHelper.Down;
        }
        return undefined;
    },
    //判断线line是否在法向量为normal的cube面或其对面上
    isLineInCubeFaceByFaceNormal: function (line, normal) {
        let startValue = Math.round(Math.abs(line.start.dot(normal)));
        let endValue = Math.round(Math.abs(line.end.dot(normal)));
        //（width,height,depth）与向量点乘
        let faceValue = Math.abs(normal.x * width + normal.y * height + normal.z * depth);
        if (startValue == 0 && endValue == 0 || startValue == faceValue && endValue == faceValue) {
            return true;
        }
        return false;
    },

    //判断平面向量是否在切面旋转范围内
    isWithinRotateRange: function (planeNormal, currentClipPlaneNormal) {
        let angle = Math.abs(planeNormal.angleTo(currentClipPlaneNormal));
        if (angle > MinRotateAngle && angle < MaxRotateAngle) {
            return true;
        }
        return false;
    },
    //重置切面信息
    resetActiveMeshInfo: function () {
        this.activeMeshInfo = undefined;
    },
    //检查当前鼠标选中的面是否被完全切掉
    isActivePlaneCompleteClipped: function () {
        if (this.activeMeshInfo == undefined)
            return true;
        let clipPlanes = this.activeMeshInfo.Mesh.Object.material.clippingPlanes;
        let existedPoints = [];
        if (clipPlanes != null) {
            let projectPoint = new THREE.Vector3();
            this.activeMeshInfo.Vertices.forEach(point => {
                if (pointIsDuplicate(existedPoints, point)) {
                    return;
                }
                //检查当前point是否被切割掉
                let isClipped = clipPlanes.some(clipPlane => {
                    clipPlane.projectPoint(point, projectPoint);
                    if (point.xyzFixedEq(projectPoint, 3)) {
                        return false;
                    }
                    let projectDirection = point.clone().sub(projectPoint);
                    //点到投影点的向量与平面夹角为锐角或直角则未被切掉
                    if (projectDirection.dot(clipPlane.normal) >= 0) {
                        return false;
                    }
                    return true;
                });
                if (!isClipped) {
                    existedPoints.push(point);
                }
            });
            if (existedPoints.length <= 2) {
                return true;
            }
            return false;
        }
        return false;
    },
    //计算当前切面可向前推动的最大距离
    setMaxForwardDistance: function () {
        let farClipPoint = this.getFarClipPoint(this.activeMeshInfo.Mesh,
            this.activeMeshInfo.Vertices);
        this.activeMeshInfo.MaxForwardDistance =
            -farClipPoint.dot(this.activeMeshInfo.Mesh.Plane.normal) + 10; //放在正方向前面一点
    },

    //计算当前切面可向前推到的最远点
    getFarClipPoint: function (clipMeshInfo, activePoints) {
        //求cube顶点到切面的最大距离
        let maxDistance = clipMeshInfo.Plane.distanceToPoint(cube.localToWorld(cube.geometry.vertices[0].clone()));
        cube.geometry.vertices.forEach(m => {
            let distance = clipMeshInfo.Plane.distanceToPoint(cube.localToWorld(m.clone()));
            if (distance > maxDistance) {
                maxDistance = distance;
            }
        });

        //获取切面中心点
        let centerPoint = PolyPointsTool.getPolyCenter(activePoints);
        var meshCenterToVertices = {
            createNew: function (line) {
                var node = {};
                node.line = line;
                node.intersectWithPlane = false;
                return node;
            }
        };

        //最远距离的顶点到切面可见中心点的连线集合
        let lineNodes = [];
        cube.geometry.vertices.forEach(m => {
            let vector = cube.localToWorld(m.clone());
            let distance = clipMeshInfo.Plane.distanceToPoint(vector);
            if (distance == maxDistance) {
                lineNodes.push(meshCenterToVertices.createNew(new THREE.Line3(centerPoint, vector)));
            }
        });

        //取与中心点的连线相交的切面
        let intersectPlanes = clipMeshInfo.Object.material.clippingPlanes.filter(m => {
            let result = false;
            lineNodes.forEach(lineNode => {
                if (m.intersectsLine(lineNode.line)) {
                    result = true;
                    //被切面挡住了就标记这根线跟面相交过
                    lineNode.intersectWithPlane = true;
                }
            });

            return result;
        });

        //如果存在未与切面相交的线，则最远距离即为cube顶点到切面的最大距离
        let lineNode = lineNodes.find(m => m.intersectWithPlane == false);
        if (lineNode != undefined) {
            return lineNode.line.end;
        }

        let farPoints = [];
        //获取所有与中心点的连线相交切面的顶点
        intersectPlanes.forEach(m => {
            let node = this.clipMeshInfos.find(n => n.Plane == m);
            let points = LineIntersectionHelper.getActiveMeshPoints(node.Object.material.clippingPlanes, node.Object.geometry.vertices, node.Plane.normal);
            farPoints = farPoints.concat(points);
        });

        //遍历顶点求出最远距离点
        let farClipPoint = undefined;
        maxDistance = 0;
        farPoints.forEach(m => {
            let distance = clipMeshInfo.Plane.distanceToPoint(m);
            if (distance > maxDistance) {
                farClipPoint = m;
                maxDistance = distance;
            }
        });

        return farClipPoint;
    },
    //添加切面信息
    addClipMeshInfo: function (clipMeshInfo) {
        cube.material.forEach(material => {
            material.clippingPlanes.push(clipMeshInfo.Plane);
        });

        this.clipMeshInfos.forEach(m => {
            m.Object.material.clippingPlanes.push(clipMeshInfo.Plane);
        });
        this.clipMeshInfos.forEach(m => {
            clipMeshInfo.Object.material.clippingPlanes.push(m.Plane);
        });
        this.clipMeshInfos.push(clipMeshInfo);
    },
    //移除纹理切面列表中的指定切面
    removeMaterialClipPlane: function (clipPlanes, clipPlane) {
        let index = clipPlanes.findIndex(n => n == clipPlane);
        if (index != -1) {
            clipPlanes.splice(index, 1);
        }
    },
    //移除无用的切面
    removeUselessClipPlane: function (newClipPlane) {
        let removeNodes = [];
        //遍历所有切面
        this.clipMeshInfos.forEach(clipMeshInfo => {
            //获取切面顶点信息
            let vertices = clipMeshInfo.Object.geometry.vertices;
            vertices = LineIntersectionHelper.getActiveMeshPoints(clipMeshInfo.Object.material.clippingPlanes, vertices, clipMeshInfo.Plane.normal);
            let projectPoint = new THREE.Vector3();
            let tempResult = [];
            //遍历所有顶点，计算顶点到新切面的投影向量与新切面法向量的点乘信息
            vertices.forEach(m => {
                newClipPlane.projectPoint(m, projectPoint);
                tempResult.push(m.clone().sub(projectPoint).dot(newClipPlane.normal));
            });

            let minValue = tempResult.min();
            let maxValue = tempResult.max();
            if (minValue * maxValue > 0){
                //切面所有顶点都在新切面的一侧
                if (maxValue < 0) {
                    //切面顶点到新切面的向量与新切面的法向量夹角的最大值为锐角，该切面需要删除
                    removeNodes.push(clipMeshInfo);
                }
            }

        });
        //删除切面
        removeNodes.forEach(m => {
            let index = this.clipMeshInfos.findIndex(n => n == m);
            if (index != -1) {
                this.removeClipPlane(index);
            }
        });
    },
    //移除所有切面
    removeAllClipPlane: function () {
        this.clipMeshInfos.forEach(m => {
            scene.remove(m.Object);
            m.dispose();
        });
        this.clipMeshInfos.splice(0, this.clipMeshInfos.length);
        cube.material.forEach(material => {
            material.clippingPlanes.splice(0, material.clippingPlanes.length);
        });

        // jsObj.DeleteAllClipImageData();
        this.resetActiveMeshInfo();       
    },

    //获取当前切割面的信息以供测量使用
    getSelectedClipInfo: function () {
        let activeMeshInfo = this.activeMeshInfo;
        if (activeMeshInfo == undefined
            || activeMeshInfo.Vertices == undefined
            || activeMeshInfo.Vertices.length < 3) {
            return undefined;
        }
        let points = [];
        activeMeshInfo.Vertices.forEach(m => {
            if (!pointIsDuplicate(points, m)) {
                points.push(m.clone());
            }
        });
        convertToVTKPoints(points);
        let mappingPoints = [];
        points.forEach(item => {
            mappingPoints.push(new cefMappingPoint(item.x, item.y, item.z));
        });
        let faceType;
        let flip = false;
        if (activeMeshInfo.MeshType == MeshType.cube) {
            faceType = CubeFaceNormalHelper.getClipFaceType(activeMeshInfo.Mesh.face.normal.clone().negate());
            flip = faceType === ClipFaceType.Left || faceType === ClipFaceType.Down || faceType === ClipFaceType.Front;
        } else {
            faceType = CubeFaceNormalHelper.getClipFaceType(activeMeshInfo.Mesh.Normal);
            if (activeMeshInfo.Mesh.Index != undefined) {
                flip = faceType === ClipFaceType.Left || faceType === ClipFaceType.Down || faceType === ClipFaceType.Front;
            }
            else {
                flip = activeMeshInfo.Mesh.Object.geometry.faces[0].b > activeMeshInfo.Mesh.Object.geometry.faces[0].c;

            }
        }

        let clipCategory = faceType === ClipFaceType.Up || faceType === ClipFaceType.Down ? ClipCategory.Soleplate : ClipCategory.Flank;
        let clipInformation = {
            PointsList: mappingPoints,
            ClipCategory: clipCategory,
            Flip: flip
        };       
        return clipInformation;
    },

    drawActiveMeshEdges: function () {
        let activeMeshInfo = this.activeMeshInfo;
        if(activeMeshInfo == undefined)
            return;
        let drawVertices;
        let clippingPlanes = activeMeshInfo.getClipPlanes();
        if (activeMeshInfo.MeshType === MeshType.cube) {
            drawVertices = getCubeFaceVertices(activeMeshInfo, clippingPlanes);
            drawVertices = LineIntersectionHelper.getActiveMeshPoints(clippingPlanes, drawVertices, activeMeshInfo.Mesh.face.normal);
        } else {
            drawVertices = activeMeshInfo.getClonedVertices();
            ClipPlaneManager.moveElementToEnd(activeMeshInfo.Mesh);
            drawVertices = LineIntersectionHelper.getActiveMeshPoints(clippingPlanes, drawVertices, activeMeshInfo.Mesh.Plane.normal);
        }
        LinesDrawingManager.showMeshEdgeLines(drawVertices, clippingPlanes);
        activeMeshInfo.Vertices = drawVertices;


        //获取选中cube面的顶点信息
        function getCubeFaceVertices(activeMeshInfo) {
            let vertices = activeMeshInfo.getClonedVertices();
            let selectedCubeFace =
                activeMeshInfo.Mesh.object.geometry.faces.find(m => m.normal == activeMeshInfo.Mesh.face.normal);
            let besideCubeFace =
                activeMeshInfo.Mesh.object.geometry.faces.find(m => m != selectedCubeFace &&
                    m.materialIndex == selectedCubeFace.materialIndex);
            let tempIndexArray = [besideCubeFace.a, besideCubeFace.b, besideCubeFace.c];
            let diagonalIndex =
                tempIndexArray.find(m => m != selectedCubeFace.a && m != selectedCubeFace.b && m != selectedCubeFace.c);

            let tempPoints = [
                vertices[selectedCubeFace.a].clone(),
                vertices[selectedCubeFace.b].clone(),
                vertices[selectedCubeFace.c].clone(),
                vertices[diagonalIndex].clone()
            ];
            tempPoints.forEach(vector => {
                cube.localToWorld(vector);
            });
            //顶点排序
            let drawVertices = PolyPointsTool.clockwiseSortPoints(tempPoints, activeMeshInfo.Mesh.face.normal);
            return drawVertices;
        }
    },
    resetClipInfo: function () {
        LinesDrawingManager.hideClipLine();
        this.removeAllClipPlane();
        removeRotateInfo();
        LinesDrawingManager.hideAll();      
    },

    meshIsActive: function () {
        if(!ClipPlaneManager.anyMeshIsActive) {
            ClipPlaneManager.anyMeshIsActive = true;
            // jsObj.MeshActiveStatusChanged(true);
            return;
        }
    },
    meshIsInactive() {
        if (ClipPlaneManager.anyMeshIsActive) {
            ClipPlaneManager.anyMeshIsActive = false;
            // jsObj.MeshActiveStatusChanged(false);
            return;
        }
    }
};