var LinesDrawingManager = {
    meshEdgeLines: undefined,
    rotateLine: undefined,
    rotateLineGeometry: new THREE.Geometry(),
    rotateLineMesh: new MeshLine(),
    clipLine: undefined,
    clipLineMaterial: new THREE.MeshBasicMaterial({ color: new THREE.Color(0x00FA9A) }),
    clipLineMultiplyMatrix: new THREE.Matrix4().set(1, 0, 0, 0,
        0, 0, 1, 0,
        0, -1, 0, 0,
        0, 0, 0, 1),
    initialMatrix: new THREE.Matrix4(),
    clipLineObject3D: new THREE.Object3D(),
    initLine: function () {
        this.initActiveLine();
        this.initRotateLine();
        this.initClipLine();
        scene.add(this.rotateLine);
        scene.add(this.meshEdgeLines);
        scene.add(this.clipLine);
        this.hideAll();
    },
    initActiveLine: function () {
        let activeLineGeometry = new THREE.BufferGeometry();
        let activeLineMaterial = new THREE.LineBasicMaterial({
            color: 0x00FA9A,
            clippingPlanes: []
        });
        this.meshEdgeLines = new THREE.Line(activeLineGeometry, activeLineMaterial);
    },
    showMeshEdgeLines: function (points, clippingPlanes) {
        if (points.length > 1) {
            points.push(points[0]);
            this.hideMeshEdgeLines();
            this.meshEdgeLines.material.clippingPlanes = clippingPlanes;
            this.meshEdgeLines.geometry.setFromPoints(points);
            this.meshEdgeLines.visible = true;
        }
    },
    hideMeshEdgeLines: function () {
        this.meshEdgeLines.visible = false;
    },

    initRotateLine: function () {
        let rotateLineMaterial = new MeshLineMaterial({
            useMap: false,
            color: new THREE.Color(0xFFFF00),
            opacity: 1,
            lineWidth: 5
        });
        this.rotateLine = new THREE.Mesh(this.rotateLineMesh.geometry, rotateLineMaterial);
    },
    showRotateLine: function (rotateLine) {
        this.rotateLineGeometry.vertices.splice(0, this.rotateLineGeometry.vertices.length);
        this.rotateLineGeometry.vertices.push(rotateLine.start, rotateLine.end);
        this.rotateLineMesh.geometry.dispose();
        this.rotateLineMesh.setGeometry(this.rotateLineGeometry);
        this.rotateLine.visible = true;
    },
    hideRotateLine: function () {
        this.rotateLine.visible = false;
    },
    initClipLine: function () {
        var meshGeometry = new THREE.CylinderBufferGeometry();
        this.clipLine = new THREE.Mesh(meshGeometry, this.clipLineMaterial);
    },
    showClipLine: function (start, end) {
        this.updateClipLineByTwoPoints(start, end);
        this.clipLine.visible = true;
    },
    hideClipLine: function () {
        this.clipLine.visible = false;
    },

    hideAll: function () {
        this.hideClipLine();
        this.hideRotateLine();
        this.hideMeshEdgeLines();
    },
    //threejs two point draw a cylinder
    //https://stackoverflow.com/questions/15316127/three-js-line-vector-to-cylinder
    updateClipLineByTwoPoints: function (start, end) {
        let height = end.distanceTo(start);
        this.clipLine.geometry.dispose();
        var meshGeometry = new THREE.CylinderBufferGeometry(2, 2, height, 8, 1);
        meshGeometry.userData = end;
        this.clipLine.geometry = meshGeometry;
        this.clipLine.matrix.lookAt(start, end, this.clipLineObject3D.up);
        this.clipLine.matrix.multiply(this.clipLineMultiplyMatrix);
        this.clipLine.applyMatrix(this.initialMatrix);
        // position based on midpoints - there may be a better solution than this
        this.clipLine.position.set((end.x + start.x) / 2, (end.y + start.y) / 2, (end.z + start.z) / 2);
    }
};