//
//  vector.js
//  examples
//
//  Created by Bridget Went on 7/1/15.
//  Copyright 2015 High Fidelity, Inc.
//
//  A template for creating vector arrows using line entities. A VectorArrow object creates a 
//  draggable vector arrow where the user clicked at a specified distance from the viewer.
//  The relative magnitude and direction of the vector may be displayed. 
//
//
//  Distributed under the Apache License, Version 2.0.
//  See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
//

var LINE_DIMENSIONS = 100;
var LIFETIME = 6000;
var RAD_TO_DEG = 180.0 / Math.PI;

var LINE_WIDTH = 4;
var ARROW_WIDTH = 6;
var line, linePosition;
var arrow1, arrow2;

var SCALE = 0.15;
var ANGLE = 150.0;


VectorArrow = function(distance, showStats, statsTitle, statsPosition) {
  this.magnitude = 0;
  this.direction = {x: 0, y: 0, z: 0};

  this.showStats = showStats;
  this.isDragging = false;

  this.newLine = function(position) {
    linePosition = position;
    var points = []; 

    line = Entities.addEntity({
      position: linePosition,
      type: "Line",
      color: {red: 255, green: 255, blue: 255},
      dimensions: {
        x: LINE_DIMENSIONS,
        y: LINE_DIMENSIONS,
        z: LINE_DIMENSIONS
      },
      lineWidth: LINE_WIDTH,
      lifetime: LIFETIME,
      linePoints: []
    });

    arrow1 = Entities.addEntity({
      position: {x: 0, y: 0, z: 0},
      type: "Line",
      dimensions: {
        x: LINE_DIMENSIONS,
        y: LINE_DIMENSIONS,
        z: LINE_DIMENSIONS
      },
      color: {red: 255, green: 255, blue: 255},
      lineWidth: ARROW_WIDTH,
      linePoints: [],
    });

    arrow2 = Entities.addEntity({
      position: {x: 0, y: 0, z: 0},
      type: "Line",
      dimensions: {
        x: LINE_DIMENSIONS,
        y: LINE_DIMENSIONS,
        z: LINE_DIMENSIONS
      },
      color: {red: 255, green: 255, blue: 255},
      lineWidth: ARROW_WIDTH,
      linePoints: [],
    });

  }


  var STATS_DIMENSIONS = {
    x: 4.0,
    y: 1.5,
    z: 0.1
  };
  var TEXT_HEIGHT = 0.3;

  this.onMousePressEvent = function(event) {
    
    this.newLine(computeWorldPoint(event));

    if (this.showStats) {
      this.label = Entities.addEntity({
        type: "Text",
        position: statsPosition,
        dimensions: STATS_DIMENSIONS,
        lineHeight: TEXT_HEIGHT,
        faceCamera: true
      });
    }

    this.isDragging = true;

  }


  this.onMouseMoveEvent = function(event) {
    
    if (!this.isDragging) {
      return;
    }

    var worldPoint = computeWorldPoint(event);
    var localPoint = computeLocalPoint(event, linePosition);
    points = [{x: 0, y: 0, z: 0}, localPoint];
    Entities.editEntity(line, { linePoints: points });

    var nextOffset = Vec3.multiply(SCALE, localPoint);
    var normOffset = Vec3.normalize(localPoint);
    var axis = Vec3.cross(normOffset, Quat.getFront(Camera.getOrientation()) );
    axis = Vec3.cross(axis, normOffset);
    var rotate1 = Quat.angleAxis(ANGLE, axis);
    var rotate2 = Quat.angleAxis(-ANGLE, axis);

    // Rotate arrow head to follow direction of the line
    Entities.editEntity(arrow1, { 
      visible: true,
      position: worldPoint,
      linePoints: [{x: 0, y: 0, z: 0}, nextOffset],
      rotation: rotate1
    });
    Entities.editEntity(arrow2, { 
      visible: true,
      position: worldPoint,
      linePoints: [{x: 0, y: 0, z: 0}, nextOffset],
      rotation: rotate2
    });

    this.magnitude = Vec3.length(localPoint) * 0.1;
    this.direction = Vec3.normalize(Vec3.subtract(worldPoint, linePosition)); 

    if (this.showStats) {
      this.editLabel(statsTitle + "                          Magnitude  " + this.magnitude.toFixed(2) + ",     Direction: " + 
                this.direction.x.toFixed(2) + ", " + this.direction.y.toFixed(2) + ", " + this.direction.z.toFixed(2));
    } 
  }

  this.onMouseReleaseEvent = function() {
    this.isDragging = false;
  }

  this.cleanup = function() {
      Entities.deleteEntity(line);
      Entities.deleteEntity(arrow1);
      Entities.deleteEntity(arrow2);
  }

  this.deleteLabel = function() {
    Entities.deleteEntity(this.label);
  }
  
  this.editLabel = function(str) {
    if(!this.showStats) {
      return;
    }
    Entities.editEntity(this.label, {
      text: str
    });
  }

  function computeWorldPoint(event) {
    var pickRay = Camera.computePickRay(event.x, event.y);
    var addVector = Vec3.multiply(pickRay.direction, distance);
    return Vec3.sum(Camera.getPosition(), addVector);
  }

  function computeLocalPoint(event, linePosition) {
      var localPoint = Vec3.subtract(computeWorldPoint(event), linePosition);
      return localPoint;
  }

}