/**
 * @fileoverview Overlay for the Geodetic Velocities visualization.
 *
 * @license Copyright 2016 Google Inc. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

// Overlay requires THREE.js and d3.
if (typeof THREE === 'undefined') {
  throw Error('THREE.js is required to create an Overlay.');
}
if (typeof d3 === 'undefined') {
  throw Error('d3 is required to create an Overlay.');
}

var geovelo;
geovelo = geovelo || {};

/**
 * Construct the overlay for the Geodetic Velocities visualization.
 *
 * @param {Element} containerElement The DOM element into which to insert.
 */
geovelo.Overlay = function(containerElement) {

  // Local reference to the geovelo settings object, throw if missing.
  var settings = geovelo.settings;
  if (!settings) {
    throw Error('geovelo.settings is missing!');
  }

  // DOM Element into which to insert content.
  this.domElement = document.createElement('div');
  this.domElement.style.pointerEvents = 'none';
  this.domElement.style.position = 'absolute';

  // Hopefully we've been provided a container and we can get a reasonable
  // bounding box. But if not, we'll set up as though we're taking up the whole
  // visible page.
  var width = window.innerWidth;
  var height = window.innerHeight;
  if (containerElement) {
    containerElement.appendChild(this.domElement);
    var rect = containerElement.getBoundingClientRect();
    width = rect.width || width;
    height = rect.height || height;
  }
  this.domElement.style.width = width + 'px';
  this.domElement.style.height = height + 'px';

  // Set up the THREE.js camera looking down the negative z axis from above,
  // with the whole frustum to the right and down. This make coordinate
  // transformations between world coordinates and screen coordinates easy.
  var camera = this.camera =
    new THREE.OrthographicCamera(0, 100, 0, -100, 0, 1000);
  camera.position.set(0, 0, 100);
  camera.updateProjectionMatrix();

  // Set up the THREE.js renderer.
  var renderer = this.renderer = new THREE.WebGLRenderer({
    alpha: true,
    antialias: false
  });
  renderer.setPixelRatio(1);
  renderer.setSize(width, height);
  style = renderer.domElement.style;
  style.pointerEvents = 'none';
  style.position = 'absolute';
  style.width = style.height = '100%';
  this.domElement.appendChild(renderer.domElement);

  // Set up the scene into which we plan to draw the Geodetic Velocity lines.
  var scene = this.scene = new THREE.Scene();

  // Set up Stats if included in the page.
  if (typeof Stats !== 'undefined') {
    var stats = this.stats = new Stats();
    stats.domElement.style.position = 'absolute';
    stats.domElement.style.top = 0;
    stats.domElement.style.left = 0;
    stats.domElement.style.display = 'none';
    this.domElement.appendChild(stats.domElement);
  }

  // Whether to show stats.
  if (settings.animation.options.showStats.defaultValue) {
    this.showStats();
  }

  // Set up the custom line shader material to use for drawing lines.
  this.material = new geovelo.LineShaderMaterial({
    linewidth: settings.style.options.lineWidth.defaultValue
  });

  // Time in ms to allow processing to hold the thread before ceding to the UI.
  this.maxProcessingTime = 100;

  // Time in ms to cede to the UI thread before resuming processing.
  this.resumeProcessingDelay = 10;

  // Time in ms to wait before invoking functions in need of debouncing.
  this.debounceTimeout = 50;

  // Animation duration and delay.
  this.animationDuration = settings.animation.options.duration.defaultValue;
  this.animationDelay = settings.animation.options.delay.defaultValue;

  // Whether we're currently animating.
  this.animating = false;
  if (settings.animation.options.enabled.defaultValue) {
    this.startAnimation();
  }
};

/**
 * Start animating.
 */
geovelo.Overlay.prototype.startAnimation = function() {
  this.animating = true;

  // The start timestamp for the current animation loop.
  var start = null;

  var animate = (function() {
    // Short-circuit if animation has been turned off.
    if (!this.animating) {
      return;
    }

    var now = Date.now();

    if (start === null) {
      start = now;
    }

    var startTimestamp = this.material.uniforms.startTimestamp.value;
    var endTimestamp = this.material.uniforms.endTimestamp.value;
    var diff = endTimestamp - startTimestamp;

    // If there's any time between the start and end timestamps, set the
    // end animation clamp and render the scene.
    if (diff) {
      this.material.uniforms.endAnimationClamp.value =
          startTimestamp + diff * (now - start) / this.animationDuration;
      this.render();
    }

    // If we've finished the loop, pause for the delay, otherwise queue up the
    // next frame.
    if (now > start + this.animationDuration) {
      start = null;
      setTimeout(animate, this.animationDelay);
    } else {
      requestAnimationFrame(animate);
    }
  }).bind(this);

  // Kick off animation loop.
  requestAnimationFrame(animate);
};

/**
 * Stop animating.
 */
geovelo.Overlay.prototype.stopAnimation = function() {
  this.animating = false;
  this.material.uniforms.endAnimationClamp.value = Infinity;
  this.queueRender();
};

/**
 * Set animation duration.
 */
geovelo.Overlay.prototype.setAnimationDuration = function(duration) {
  this.animationDuration = duration;
};

/**
 * Set animation delay.
 */
geovelo.Overlay.prototype.setAnimationDelay = function(delay) {
  this.animationDelay = delay;
};

/**
 * Show the FPS stats display.
 */
geovelo.Overlay.prototype.showStats = function() {
  if (this.stats) {
    this.stats.domElement.style.display = null;
  }
};

/**
 * Hide the FPS stats display.
 */
geovelo.Overlay.prototype.hideStats = function() {
  if (this.stats) {
    this.stats.domElement.style.display = 'none';
  }
};

/**
 * Render the overlay into the canvas.
 */
geovelo.Overlay.prototype.render = function() {
  this.renderQueued = false;
  this.renderer.render(this.scene, this.camera);
  if (this.stats) {
    this.stats.update();
  }
};

/**
 * Queue up a future call to render.
 */
geovelo.Overlay.prototype.queueRender = function() {
  if (!this.renderQueued) {
    this.renderQueued = true;
    requestAnimationFrame(this.render.bind(this));
  }
};

/**
 * Set the boundaries of the viewable area in terms of minimum and maximum
 * longitude and latitude. If the bounds object includes usable width, height
 * and/or position values (left, right, bottom, top), then these will be used
 * for the renderer well.
 *
 * @param {Object} bounds An object with north, south, east and west properties
 * which map to the latitudinal and longitudinal extent. May also include width
 * and heigt properties for the viewport.
 */
geovelo.Overlay.prototype.setBounds = function(bounds) {
  clearTimeout(this.setBoundsTimer);

  var getX = geovelo.WebMercator.getX;
  var getY = geovelo.WebMercator.getY;

  var minx = getX(bounds.west);
  var maxx = getX(bounds.east);
  var miny = getY(bounds.south);
  var maxy = getY(bounds.north);

  this.camera.right = maxx - minx;
  this.camera.bottom = -(maxy - miny);
  this.camera.position.set(minx, maxy, 100);
  this.camera.updateProjectionMatrix();

  // The overlay element always wants to align with the map's bounding box,
  // irrespective of where its ancestors are positiond to that point.
  var parent = this.domElement.parentNode.getBoundingClientRect();
  this.domElement.style.top = (bounds.top - parent.top) + 'px';
  this.domElement.style.left = (bounds.left - parent.left) + 'px';
  this.domElement.style.bottom = (bounds.bottom - parent.bottom) + 'px';
  this.domElement.style.right = (bounds.right - parent.right) + 'px';

  if (bounds.width && bounds.height) {
    this.renderer.setSize(bounds.width, bounds.height);
  }

  this.render();
};

/**
 * Queue up a future call to setBounds() to debounce frequent updates.
 * @see setBounds().
 */
geovelo.Overlay.prototype.queueSetBounds = function(bounds) {
  clearTimeout(this.setBoundsTimer);
  this.setBoundsTimer =
      setTimeout(this.setBounds.bind(this, bounds), this.debounceTimeout);
};

/**
 * New beacon data is available. Preprocess the data and reconstruct the scene.
 * @param {Array} rawBeacons An array of data for the beacons.
 */
geovelo.Overlay.prototype.setData = function(rawBeacons) {

  /**
   * This object keeps track of how the data processing is going.
   */
  this.processState = {

    // Total number of vertices that we'll have.
    totalVertexCount: 0,

    // Raw beacon data.
    rawBeacons: rawBeacons,

    // Processed beacon data.
    processedBeacons: []

  };

  // Begin processing the data by determining the total vertex count.
  this.analyzeData(true);

};

/**
 * Convenience method for emitting a status update event.
 *
 * @param {string} status Description of what's going on.
 * @param {number} progress Estimate of progress (0-1).
 */
geovelo.Overlay.prototype.emitStatusUpdate = function(status, progress) {
  this.domElement.dispatchEvent(new CustomEvent('status-update', {
        bubbles: true,
        detail: {
          status: status,
          progress: progress
        }
      }));
};

/**
 * Count the total number of vertices that we'll end up with in the final line,
 * and also find out the minimum and maximum timestamps.
 *
 * @param {boolean} init Set to true to initialize state (first call).
 */
geovelo.Overlay.prototype.analyzeData = function(init) {

  var state = this.processState;

  if (init) {
    state.beaconIndex = 0;
    state.startTimestamp = Infinity;
    state.endTimestamp = -Infinity;
  }

  var rawBeacons = state.rawBeacons;

  var start = Date.now();
  while (state.beaconIndex < rawBeacons.length) {
    var beacon = rawBeacons[state.beaconIndex];

    // To save on the number of objects vertices that we have to render, we
    // construct one big geometry rather than thousands of smaller ones. So we
    // cram all of the beacons' lines into one big vertex array, adding in
    // separator vertices to break the line. Line segments that involve these
    // separator vertices are discarded in the shader.
    state.totalVertexCount += beacon.lon.length + 2;

    state.startTimestamp = Math.min(state.startTimestamp, beacon.start);
    state.endTimestamp = Math.max(state.endTimestamp,
        beacon.start + beacon.lon.length * 60 * 60 * 24);

    state.beaconIndex++;

    if (Date.now() - start >= this.maxProcessingTime) {
      // Announce progress, then cede to the UI thread.
      this.emitStatusUpdate('analyzing data...',
          state.beaconIndex / rawBeacons.length);
      return setTimeout(
          this.analyzeData.bind(this), this.resumeProcessingDelay);
    }
  }

  // Announce timestamp extent for controls.
  this.domElement.dispatchEvent(new CustomEvent('extent-changed', {
        bubbles: true,
        detail: {
          extentStart: new Date(state.startTimestamp * 1000),
          extentEnd: new Date(state.endTimestamp * 1000)
        }
      }));

  // Set up the buffers, geometries and lines for further processing.
  this.setupBuffers();
};

/**
 * Since the total vertex count is now known, set up buffers to hold vertex
 * data and begin processing vertex data.
 */
geovelo.Overlay.prototype.setupBuffers = function() {

  var state = this.processState;

  // Create typed array to hold each vertex's relevant attributes:
  //  - x - the beacon index,
  //  - y - the beacon's start timestamp,
  //  - z - the current timestamp.
  // These are used by the LineShaderMaterial's vertex shader to compute
  // final positions based on values retrieved from the BeaconVertexTexture.
  state.positions = new Float32Array(state.totalVertexCount * 3);

  // The beacon vertext texture holds all the data about each beacon at each
  // timestamp that the shader needs.
  // @see geovelo.BeaconVertexTexture.
  var texture = state.texture = new geovelo.BeaconVertexTexture(
      state.rawBeacons.length, state.startTimestamp, state.endTimestamp);
  this.material.setBeaconVertexTexture(texture);

  // Create a geometry and line for the scene. At this point we can safely begin
  // rendereing, even though the actual values haven't been filled in yet.
  var geometry = state.geometry = new THREE.BufferGeometry();
  geometry.addAttribute('position',
      new THREE.BufferAttribute(state.positions, 3));
  var line = state.line = new THREE.Line(geometry, this.material);
  line.frustumCulled = false;
  this.scene.add(line);

  // Begin processing beacon data.
  this.processData(true);
};

/**
 * Perform data processing for a time before ceding back to the UI thread.
 *
 * @param {boolean} init Set to true to initialize processing (first call).
 */
geovelo.Overlay.prototype.processData = function(init) {

  var state = this.processState;

  if (init) {
    state.beaconIndex = 0;
    state.positionIndex = 0;
  }

  var rawBeacons = state.rawBeacons;

  var getX = geovelo.WebMercator.getX;
  var getY = geovelo.WebMercator.getY;

  var start = Date.now();
  while (state.beaconIndex < rawBeacons.length) {

    var beacon = rawBeacons[state.beaconIndex];

    // This object keeps track of the processing of an individual beacon.
    var beaconState = state.beaconState;
    if (!beaconState) {
      beaconState = state.beaconState = {

        // The name of this beacon.
        name: beacon.name,

        // The beacon's base X and Y position in Web Mercator projected coords.
        baseX: getX(beacon.lon[0]),
        baseY: getY(beacon.lat[0]),

        // The index within the beacon's lon/lat arrays to look at next.
        lonLatIndex: 0

      };

      state.texture.setBaseLonLat(
          state.beaconIndex, beaconState.baseX, beaconState.baseY);
    }

    while (beaconState.lonLatIndex < beacon.lon.length) {

      var lon = beacon.lon[beaconState.lonLatIndex];
      var lat = beacon.lat[beaconState.lonLatIndex];

      if (lon && lat) {

        var x = getX(lon) - beaconState.baseX;
        var y = getY(lat) - beaconState.baseY;
        var timestamp = beacon.start + beaconState.lonLatIndex * 60 * 60 * 24;

        // Poke the x and y values into the texture.
        state.texture.setBeaconLonLat(state.beaconIndex, timestamp, x, y);

        if (beaconState.lonLatIndex === 0) {
          // Insert a separator vertex since we're beginning a beacon.
          state.positions[state.positionIndex * 3 + 0] = state.beaconIndex;
          state.positions[state.positionIndex * 3 + 1] = beacon.start;
          state.positions[state.positionIndex * 3 + 2] = -Infinity;
          state.positionIndex++;
        }

        // Insert a vertex for this beacon and timestamp.
        state.positions[state.positionIndex * 3 + 0] = state.beaconIndex;
        state.positions[state.positionIndex * 3 + 1] = beacon.start;
        state.positions[state.positionIndex * 3 + 2] = timestamp;
        state.positionIndex++;

        if (beaconState.lonLatIndex === beacon.lon.length - 1) {
          // Insert a separator vertex since we're at the end of a beacon.
          state.positions[state.positionIndex * 3 + 0] = state.beaconIndex;
          state.positions[state.positionIndex * 3 + 1] = beacon.start;
          state.positions[state.positionIndex * 3 + 2] = Infinity;
          state.positionIndex++;
        }

        state.geometry.attributes.position.needsUpdate = true;

      }

      beaconState.lonLatIndex++;

      if (Date.now() - start >= this.maxProcessingTime) {
        // Announce progress, then cede to the UI thread.
        this.emitStatusUpdate('adding beacon lines...',
            state.beaconIndex / rawBeacons.length);
        return setTimeout(
            this.processData.bind(this), this.resumeProcessingDelay);
      }
    }

    // Finished with this beacon! Save off the beacon state object for further
    // processing.
    state.processedBeacons[state.beaconIndex] = beaconState;

    // Clear out the beaconState object, increment beaconIndex.
    state.beaconState = null;
    state.beaconIndex++;
    state.progress = state.beaconIndex / rawBeacons.length;

    this.material.needsUpdate = true;
    this.queueRender();
  }

  this.beacons = state.processedBeacons;

  // Compute medians for correction.
  this.computeMedians(true);

};

/**
 * Compute and update the cumulative median offset lon/lat values.
 *
 * @param {boolean} init Set to true to initialize processing (first call).
 */
geovelo.Overlay.prototype.computeMedians = function(init) {

  var SECONDS_PER_DAY = 60 * 60 * 24;
  var getX = geovelo.WebMercator.getX;
  var getY = geovelo.WebMercator.getY;

  var state = this.processState;

  if (init) {
    state.currentTimestamp = state.startTimestamp;
    state.medianLons = [];
    state.medianLats = [];
  }

  var start = Date.now();
  while (state.currentTimestamp <= state.endTimestamp) {

    // Lists of all of the longitudinal and latitudinal deltas for all beacons
    // that have data for this timestamp. These will be sorted to pick out the
    // median, and then that will be added to the previous cumulative median to
    // get the new cumulative median.
    var deltaLons = [];
    var deltaLats = [];

    for (var j = 0; j < state.rawBeacons.length; j++) {

      var beacon = state.rawBeacons[j];

      // Skip this beacon if the current timestamp is either before its first
      // reading or after its last.
      if (state.currentTimestamp < beacon.start) {
        continue;
      }
      var endTimestamp = beacon.start + SECONDS_PER_DAY * beacon.lon.length;
      if (state.currentTimestamp > endTimestamp) {
        continue;
      }

      // Look up the lon and lat values for this beacon.
      var index = Math.round(
          (state.currentTimestamp - beacon.start) / SECONDS_PER_DAY);
      var lon = beacon.lon[index];
      var lat = beacon.lat[index];

      if (lon && lat) {
        // Data's not missing, add to arrays.
        var prevLon = state.texture.getLon
        var beaconState = state.processedBeacons[j];

        // Look up the previous lon and lat values, may have to slide backwards
        // over missing data.
        var prevLon = 0;
        var prevLat = 0;
        var prevIndex = index - 1;
        while (prevIndex >= 0 && (!prevLon || !prevLat)) {
          prevLon = beacon.lon[prevIndex];
          prevLat = beacon.lat[prevIndex];
          prevIndex--;
        }

        if (!prevLon || !prevLat) {
          // Couldn't find a previous lon/lat to diff against.
          continue;
        }

        // Add each delta to the appropriate list.
        deltaLons.push(getX(lon) - getX(prevLon));
        deltaLats.push(getY(lat) - getY(prevLat));
      }

    }

    // Add current medians to cumulative medians and set in texture.
    var cumulativeMedianLon =
        (d3.median(deltaLons) || 0.0) +
        (state.medianLons[state.medianLons.length - 1] || 0);
    var cumulativeMedianLat =
        (d3.median(deltaLats) || 0.0) +
        (state.medianLats[state.medianLats.length - 1] || 0);
    state.medianLons.push(cumulativeMedianLon);
    state.medianLats.push(cumulativeMedianLat);
    state.texture.setMedianLonLat(
        state.currentTimestamp, cumulativeMedianLon, cumulativeMedianLat);

    state.currentTimestamp += SECONDS_PER_DAY;

    this.queueRender();

    if (Date.now() - start >= this.maxProcessingTime) {
      // Announce progress, then cede to the UI thread.
      this.emitStatusUpdate('computing medians...',
          (state.currentTimestamp - state.startTimestamp) /
          (state.endTimestamp - state.startTimestamp));
      return setTimeout(
          this.computeMedians.bind(this), this.resumeProcessingDelay);
    }
  }

  this.emitStatusUpdate('ready', 1);

};

/**
 * Set the color to use for the start of the range.
 *
 * @param {string} startColor The color to set for the start of the range.
 */
geovelo.Overlay.prototype.setStartColor = function(startColor) {
  var color = d3.rgb(startColor);
  this.material.uniforms.startColor.value
      .set(color.r / 255, color.g / 255, color.b / 255, 1);
  this.queueRender();
};

/**
 * Set the color to use for the end of the range.
 *
 * @param {string} endColor The color to set for the end of the range.
 */
geovelo.Overlay.prototype.setEndColor = function(endColor) {
  var color = d3.rgb(endColor);
  this.material.uniforms.endColor.value
      .set(color.r / 255, color.g / 255, color.b / 255, 1);
  this.queueRender();
};

/**
 * Set the line width.
 */
geovelo.Overlay.prototype.setLineWidth = function(lineWidth) {
  this.material.linewidth = lineWidth;
  this.queueRender();
};

/**
 * Set the starting timestamp of the line shader material. This will map to the
 * start color and start opacity.
 *
 * @param {number} startTimestamp Unix timestamp of the start of the range.
 */
geovelo.Overlay.prototype.setStartTimestamp = function(startTimestamp) {
  this.material.setStartTimestamp(startTimestamp);
  this.queueRender();
};

/**
 * Set the ending timestamp of the line shader material. This will map to the
 * end color and start opacity.
 *
 * @param {number} endTimestamp Unix timestamp of the end of the range.
 */
geovelo.Overlay.prototype.setEndTimestamp = function(endTimestamp) {
  this.material.setEndTimestamp(endTimestamp);
  this.queueRender();
};

/**
 * Set the scale on the LineShaderMaterial from the provided multiplier.
 */
geovelo.Overlay.prototype.setMultiplier = function(multiplier) {
  this.material.setScale(Math.pow(10, multiplier));
  this.queueRender();
};

/**
 * Set the amount of median correction to apply.
 */
geovelo.Overlay.prototype.setMedianCorrection = function(medianCorrection) {
  this.material.setMedianCorrection(medianCorrection);
  this.queueRender();
};

/**
 * Set the amount of median correction on the LineShaderMaterial.
 *
 * @param {number} correction Value from 0 (no correction) to 1 (full).
 */
geovelo.Overlay.prototype.setMedianCorrection = function(correction) {
  this.material.setMedianCorrection(correction);
  this.queueRender();
};

/**
 * Given an array of numbers (like latitude or longitude), return how many
 * elements have falsey values.
 */
geovelo.Overlay.countMissing = function(array) {
  var missing = 0;
  for (var i = 0; i < array.length; i++) {
    missing += !array[i];
  }
  return missing;
};
