// Copyright 2015 The Vanadium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

require('es6-shim');

var $ = require('../util/jquery');
var defineClass = require('../util/define-class');

var _ = require('lodash');
var Multimap = require('multimap');

var marshalling = require('./marshalling');
var SyncbaseWrapper = require('../vanadium-wrapper/syncbase-wrapper');
var escape = SyncbaseWrapper.escapeKeyElement;
var unescape = SyncbaseWrapper.unescapeKeyElement;

var HEARTBEAT_PERIOD = 2500; //ms
var DEVICE_SEEN_RECENTLY = 5000; //ms

var LEFT = 'left';
var RIGHT = 'right';
var UP = 'up';
var DOWN = 'down';
var FORWARDS = 'forwards';
var BACKWARDS = 'backwards';

var NEAR = 'near';
var FAR = 'far';

var RE = 6.371e6;

function cartesian(geo) {
  var lat = geo.latitude * Math.PI / 180;
  var lng = geo.longitude * Math.PI / 180;
  var planeFactor = Math.cos(lng);

  return {
    x: RE * Math.cos(lat) * planeFactor,
    y: RE * Math.sin(lat) * planeFactor,
    z: RE * Math.sin(lng)
  };
}

function negateVector(vector) {
  return {
    x: -vector.x,
    y: -vector.y,
    z: -vector.z
  };
}

function negateDirection(direction) {
  switch(direction) {
  case LEFT:
    return RIGHT;
  case RIGHT:
    return LEFT;
  case UP:
    return DOWN;
  case DOWN:
    return UP;
  case FORWARDS:
    return BACKWARDS;
  case BACKWARDS:
    return FORWARDS;
  default:
    return {
      mean: negateVector(direction.mean),
      margin: direction.margin
    };
  }
}

var DeviceSync = defineClass({
  statics: {
    LEFT: LEFT,
    RIGHT: RIGHT,
    UP: UP,
    DOWN: DOWN,
    FORWARDS: FORWARDS,
    BACKWARDS: BACKWARDS,
    NEAR: NEAR,
    FAR: FAR,

    deviceKey: function(owner, device) {
      var mutableArgs = _.flattenDeep(arguments);
      //arguments 0 and 1 are a username and device ID, respectively
      //if present, arguments 3 and 4 are that way too
      for (var i = 0; i <= 4; i++) {
        if (mutableArgs[i] && i !== 2) {
          mutableArgs[i] = escape(mutableArgs[i]);
        }
      }
      return ['devices'].concat(mutableArgs);
    },

    negateRelativePosition: function(relativePosition) {
      return {
        direction: negateDirection(relativePosition.direction),
        magnitude: relativePosition.magnitude
      };
    }
  },

  publics: {
    relate: function(remoteOwner, remoteDevice, relativePosition) {
      var self = this;

      return this.identityPromise.then(function(identity) {
        return self.sbw.batch(function(ops) {
          return Promise.all([
            self.relateUnidirectional(ops,
              identity.username, identity.deviceName,
              remoteOwner, remoteDevice,
              relativePosition),
            self.relateUnidirectional(ops,
              remoteOwner, remoteDevice,
              identity.username, identity.deviceName,
              self.negateRelativePosition(relativePosition))]);
        });
      });
    },

    getRelatedDevices: function(direction) {
      return this.relatedDevices.get(direction) || new Multimap();
    },

    getUnconnectedCastTargets: function() {
      return this.unconnectedCastTargets;
    },

    getPossibleCastTargets: function() {
      return this.possibleCastTargets;
    },

    processDevices: function(data) {
      var self = this;
      var now = Date.now();
      var possibleCastTargets = new Multimap();
      var unconnectedCastTargets = new Multimap();
      var connections;

      this.identityPromise.then(function(identity) {
        var hasCastTargets;
        $.each(data, function(owner, devices) {
          owner = unescape(owner);

          $.each(devices, function(deviceName, deviceData) {
            deviceName = unescape(deviceName);
            if (owner === identity.username &&
                deviceName === identity.deviceName) {
              connections = deviceData.connections;
            } else if (now - deviceData.lastSeen <= DEVICE_SEEN_RECENTLY) {
              var deviceLocation = marshalling.unmarshal(deviceData.location);
              var isNearby = self.isNearby(deviceLocation);

              if (isNearby !== false) {
                hasCastTargets = true;
                possibleCastTargets.set(owner, deviceName);
                unconnectedCastTargets.set(owner, deviceName);
              }
            }
          });
        });

        /* This could just be a multimap of direction => {owner, deviceName},
         * but to keep the interface consistent we should have the RHS be a
         * multimap of owner => deviceName. */
        var relatedDevices = new Map();

        if (connections) {
          $.each(connections, function(owner, devices) {
            owner = unescape(owner);
            $.each(devices, function(deviceName, relPos) {
              deviceName = unescape(deviceName);
              if (unconnectedCastTargets.has(owner, deviceName)) {
                relPos = marshalling.unmarshal(relPos);
                // TODO(rosswang): handle vector directions
                var bucket = relatedDevices.get(relPos.direction);
                if (!bucket) {
                  relatedDevices.set(relPos.direction, bucket = new Multimap());
                }

                bucket.set(owner, deviceName);
                unconnectedCastTargets.delete(owner, deviceName);
              }
            });
          });
        }

        if (hasCastTargets && !self.hasCastTargets) {
          self.onPossibleNearbyDevices();
        }

        self.hasCastTargets = hasCastTargets;
        self.possibleCastTargets = possibleCastTargets;
        self.unconnectedCastTargets = unconnectedCastTargets;
        self.relatedDevices = relatedDevices;
      }).catch(this.onError);
    },

    /*
     * Adds or updates an "extend" screencast with the given control points.
     * @param remoteName the Vanadium name of the remote RPC server.
     * @param adjustment normalized adjustment in local coordinates, { x, y }
     *
    extendTo: function(remoteName, adjustment) {
      if (!this.deviceSetId) {
        this.deviceSetId = uuid.v4();
      }

      return this.sbw.put(
        this.deviceSetKey(this.deviceSetId, this.localName, remoteName),
        marshalling.marshal(adjustment));
    },

    handleBoundsUpdate: function(newBounds) {
      var self = this;
      var deviceSetId = this.deviceSetId;
      this.localBounds = newBounds;

      if (this.currentBoundsUpdate) {
        return this.currentBoundsUpdate;
      } else {
        if (deviceSetId) {
          this.currentBoundsUpdate = this.runOrQueueBoundsUpdate()
            .catch(function(err) {
              delete self.currentBoundsUpdate;
              throw err;
            });
          return this.currentBoundsUpdate;
        } else {
          return Promise.resolve();
        }
      }
    }*/
  },

  privates: {
    relateUnidirectional: function(dao, fromOwner, fromDevice,
        toOwner, toDevice, relativePosition) {
      return dao.put(this.deviceKey(
        fromOwner, fromDevice, 'connections', toOwner, toDevice),
        marshalling.marshal(relativePosition));
    },

    heartbeat: function() {
      var self = this;
      return this.identityPromise.then(function(identity) {
        return self.sbw.put(
          self.deviceKey(identity.username, identity.deviceName, 'lastSeen'),
          Date.now());
      });
    },

    updateGeolocation: function(geolocation) {
      var self = this;

      this.geolocation = geolocation;

      return this.identityPromise.then(function(identity) {
        return self.sbw.put(
          self.deviceKey(identity.username, identity.deviceName, 'location'),
          self.serializeGeolocation(geolocation));
      });
    },

    /**
     * The properties on these objects don't appear to be enumerable, so
     * serialize them explicitly here.
     */
    serializeGeolocation: function(geolocation) {
      var coords = geolocation.coords;
      return marshalling.marshal({
        coords: {
          accuracy: coords.accuracy,
          altitude: coords.altitude,
          altitudeAccuracy: coords.altitudeAccuracy,
          heading: coords.heading,
          latitude: coords.latitude,
          longitude: coords.longitude,
          speed: coords.speed
        },
        timestamp: geolocation.timestamp
      });
    },

    /**
     * The true calculation here would involve the distance between two
     * cylinders in spherical space... let's just punt on that for now.
     *
     * TODO(rosswang): find a library or factor this out.
     * location-math seems ideal but doesn't seem to contain any code
     * coordinate-systems may be suitable
     *
     * Also, if we keep doing this based on Cartesian coordinates, cache the
     * current Cartesian location.
     */
    isNearby: function(geolocation) {
      var a = this.geolocation && this.geolocation.coords || {};
      var b = geolocation && geolocation.coords || {};

      if (typeof a.altitude === 'number' && typeof b.altitude === 'number' &&
          typeof a.altitudeAccuracy === 'number' &&
          typeof b.altitudeAccuracy === 'number' &&
          Math.abs(a.altitude - b.altitude) >
          a.altitudeAccuracy + b.altitudeAccuracy + 50) {
        return false;
      }

      if (typeof a.latitude === 'number' && typeof b.latitude === 'number' &&
          typeof a.longitude === 'number' && typeof b.longitude === 'number' &&
          typeof a.accuracy === 'number' && typeof b.accuracy === 'number') {
        var va = cartesian(a);
        var vb = cartesian(b);

        var vd = {
          x: va.x - vb.x,
          y: va.y - vb.y,
          z: va.z - vb.z
        };
        var tolerance = a.accuracy + b.accuracy + 50;

        return vd.x * vd.x + vd.y * vd.y + vd.z * vd.z <= tolerance * tolerance;
      }

      //else return undefined
    }

    /*
    runOrQueueBoundsUpdate: function() {
      var self = this;
      var delay = this.lastBoundsUpdate === undefined? 0 :
        MIN_UPDATE_PERIOD - (Date.now() - this.lastBoundsUpdate);
      console.debug(delay);
      if (delay > 0) {
        return new Promise(function(resolve, reject) {
          setTimeout(function() {
            resolve(self.runCurrentBoundsUpdate());
          }, delay);
        });
      } else {
        return this.runCurrentBoundsUpdate();
      }
    },

    runCurrentBoundsUpdate: function() {
      var self = this;
      var deviceSetId = this.deviceSetId;
      if (deviceSetId) {
        console.debug('update');
        this.lastBoundsUpdate = Date.now();

        return this.sbw.pull(this.deviceSetKey(deviceSetId))
        .then(function(data) {
          var update = self.updateNeighborsBounds(
            data.deviceSets[deviceSetId], self.localBounds);
          delete self.currentBoundsUpdate;
          return update;
        });
      } else {
        delete this.currentBoundsUpdate;
        return Promise.resolve();
      }
    },

    updateNeighborsBounds: function(deviceSetData, bounds) {
      var self = this;

      var promises = [];

      var lnEsc = SyncbaseWrapper.escapeKeyElement(this.localName);

      var forwardsNeighbors = deviceSetData[lnEsc];
      $.each(forwardsNeighbors, function(neighborName, adjustment) {
        promises.push(self.updateNeighborBounds(
          SyncbaseWrapper.unescapeKeyElement(neighborName),
          bounds, marshalling.unmarshal(adjustment)));
      });

      $.each(deviceSetData, function(neighborName, neighborNeighbors) {
        if (neighborName !== lnEsc) {
          var invAdjustment = marshalling.unmarshal(neighborNeighbors[lnEsc]);
          if (invAdjustment) {
            var adjustment = {
              x: -invAdjustment.x,
              y: -invAdjustment.y
            };
            promises.push(self.updateNeighborBounds(
              SyncbaseWrapper.unescapeKeyElement(neighborName),
              bounds, adjustment));
          }
        }
      });

      return Promise.all(promises);
    },

    transform: function(bounds, adjustment) {
      var sw = bounds.getSouthWest();
      var ne = bounds.getNorthEast();
      var span = bounds.toSpan();

      var offset = new this.maps.LatLng(
        adjustment.y * span.lat(),
        adjustment.x * span.lng());

      return new this.maps.LatLngBounds(
        new this.maps.LatLng(sw.lat() + offset.lat(), sw.lng() + offset.lng()),
        new this.maps.LatLng(ne.lat() + offset.lat(), ne.lng() + offset.lng()));
    },

    updateNeighborBounds: function(name, bounds, adjustment) {
      var neighborBounds = this.transform(bounds, adjustment);
      return this.updateRemoteBounds(name, neighborBounds);
    },

    handleMouseMove: function(e) {
    }*/
  },

  events: {
    onError: 'memory',
    /**
     * Triggered when devices are discovered (possibly) nearby, where none were
     * present before.
     */
    onPossibleNearbyDevices: ''
  },

  init: function(maps, identityPromise, deferredSyncbaseWrapper) {
    var self = this;

    this.maps = maps;
    this.identityPromise = identityPromise;
    this.sbw = deferredSyncbaseWrapper;

    function heartbeatLoop() {
      self.heartbeat();
      setTimeout(heartbeatLoop, HEARTBEAT_PERIOD);
    }
    process.nextTick(heartbeatLoop);

    if (global.navigator && global.navigator.geolocation) {
      global.navigator.geolocation.watchPosition(this.updateGeolocation);
    }
  }
});

module.exports = DeviceSync;