/// <reference path="ConeTreeVisualisation.ts" />
/// <reference path="ConeTreeNode.ts" />
/// <reference path="../resources/three.d.ts" />
/// <reference path="../debugPrinter.ts" />
/// <reference path="../FDEventHandler.ts" />
/// <reference path="../FDHelpers.ts" />
module FD {
    export class ConeTreeEventHandler extends FDEventHandler {

        private mouseDownPosition: THREE.Vector2;
        public mouseDown = false;
        private selected: FDNode;
        private selectedMat: THREE.Material;
        private animate: Boolean;

        constructor(debug: boolean, fluidDiagrams: FluidDiagrams) {

            super(debug, fluidDiagrams);
            this.mouseDownPosition = new THREE.Vector2();
            this.selected = null;
            this.animate = true;
        }


        public onMouseDown(e: Event) {
            //debugPrinter.print("ConeTree MouseDown", this.debug);
            this.mouseDownPosition.x = (<any>e).clientX;
            this.mouseDownPosition.y = (<any>e).clientY;
            this.mouseDown = true;

        }

        public onMouseUp(e: Event) {
            // debugPrinter.print("ConeTree MouseUp", this.debug);
            this.mouseDown = false;
        }

        public onMouseClick(e: Event, element) {
            //node could be a actual node or a non node scene element

            if (element != null && element instanceof FDNode) {
                if (this.selected != null) {
                    this.selected.getAllGeometry()[0].material = this.selectedMat;
                }
                this.selected = element;
                this.selectedMat = element.getAllGeometry()[0].material;
                element.getAllGeometry()[0].material = <any>new THREE.MeshBasicMaterial({ color: 0xffffff });
                this.rotateRecursive(element);
                //recursive up
            }
        }

        public onMouseMove(e: Event) {
            if (this.mouseDown === true) {
                var x = (<any>e).clientX - this.mouseDownPosition.x;
                var y = (<any>e).clientY - this.mouseDownPosition.y;

                this.fluidDiagrams.camera.translateX(-x / 2);
                this.fluidDiagrams.camera.translateY(y / 2);
                this.mouseDownPosition.x = (<any>e).clientX;
                this.mouseDownPosition.y = (<any>e).clientY;
            }
        }

        public mouseWheel(e: Event) {

            var ev = window.event || e;
            var delta = Math.max(-1, Math.min(1, (<any>ev).wheelDelta || -(<any>e).detail));

            //camera looks at -z in camera space (we can use this to move forward and backward)

            var zoom = (<THREE.CombinedCamera>this.fluidDiagrams.camera).zoom;
            if (zoom >= 0.2) {
                var newZoom = zoom + delta / 10;
                newZoom <= 0.2 ? 0.2 : newZoom;
                (<THREE.CombinedCamera>this.fluidDiagrams.camera).setZoom(newZoom);
            } else {
                (<THREE.CombinedCamera>this.fluidDiagrams.camera).setZoom(0.2);
            }

        }

        public update() {
 
        }

        private rotateRecursive(node: FDNode) {

            if (node.getParent() != null) {

                var currentPossition = node.getWorldCoordinates();//position of sphere mesh
                var parentPossition = node.getParent().getWorldCoordinates();

                //calculate angel between old and new possition on x/z plane 
                //debugPrinter.print("node current pos " + currentPossition.x + "/" + currentPossition.z, this.debug);
                var tarz = parentPossition.z + (<ConeTreeNode>node.getParent()).radius;
                var tarx = parentPossition.x;
                //debugPrinter.print("target of rotation: " + tarx + "/" + tarz, this.debug);

                var phi = threePointAngle(new THREE.Vector2(currentPossition.x, currentPossition.z), //current
                    new THREE.Vector2(parentPossition.x, parentPossition.z), //pivot
                    new THREE.Vector2(tarx, tarz)); //target


                var correction = this.rotateRecursive(node.getParent());

                

                //correct rotaion
                if (correction >= 0 && currentPossition.x < parentPossition.x) {
                    phi = phi - correction;
                } else if (correction >= 0 && currentPossition.x > parentPossition.x) {
                    phi = -phi - correction;
                } else if (correction < 0 && currentPossition.x < parentPossition.x) {
                    phi = phi + (correction * -1);
                } else if (correction < 0 && currentPossition.x > parentPossition.x) {
                    phi = -phi - correction;
                }
                var cor = phi + correction;
                //using TWEEN.js to animate
                if (!isNaN(phi)) {
                    var phi_ = node.getParent().getNodeSceneGraph().rotation.y + phi;//make rotation absolute

                    if (this.animate === true) {
                        var parenttween = new TWEEN.Tween(node.getParent().getNodeSceneGraph().rotation).to({ y: phi_ }, 2000).start();
                    } else {
                        node.getParent().getNodeSceneGraph().rotation.y = phi_;
                    }

                    return cor;
                } else {
                    return 0;
                }


            } else {
                return 0;
            }
        }

        public toggleShadows(active: Boolean) {
            if (active == false) {
                for (var len = 0; len < (<ConeTreeVisualisation>this.fluidDiagrams.getVisualisation()).shadows.length; len++) {
                    (<ConeTreeVisualisation>this.fluidDiagrams.getVisualisation()).shadows[len].visible = false;
                }
            } else {
                for (var len = 0; len < (<ConeTreeVisualisation>this.fluidDiagrams.getVisualisation()).shadows.length; len++) {
                    (<ConeTreeVisualisation>this.fluidDiagrams.getVisualisation()).shadows[len].visible = true;
                }
            }
            
            
        }

        public toggleLabels(active: Boolean) {
            if (active == false) {
                for (var len = 0; len < (<ConeTreeVisualisation>this.fluidDiagrams.getVisualisation()).labels.length; len++) {
                    (<ConeTreeVisualisation>this.fluidDiagrams.getVisualisation()).labels[len].visible = false;
                }
            } else {
                for (var len = 0; len < (<ConeTreeVisualisation>this.fluidDiagrams.getVisualisation()).labels.length; len++) {
                    (<ConeTreeVisualisation>this.fluidDiagrams.getVisualisation()).labels[len].visible = true;
                }
            }
        }

        public toggleAnimation(active: Boolean) {
            this.animate = active;
        }
    }
}
