/*jslint nomen: true, indent: 2, maxerr: 3, maxlen: 80 */
/*global console, me*/

(function (console, me) {
  "use strict";

  var ALTITUDE = 100,
    EPSILON = 9,
    CHECKPOINT_LIST = [],
    DIRECTION_LIST = [
      {
        distance: 1053,
        bearing: 293
      },
      {
        distance: 800,
        bearing: 104
      },
      {
        distance: 669,
        bearing: 352
      },
      {
        distance: 925,
        bearing: 162
      },
      {
        distance: 690,
        bearing: 47
      },
      {
        distance: 935,
        bearing: 166
      },
      {
        distance: 1129,
        bearing: 289
      },
      {
        distance: 520,
        bearing: 94
      }
    ],
    R = 6371e3; // meters

  function to_deg(rad) {
    return rad * 180 / Math.PI;
  }

  function to_rad(deg) {
    return deg * Math.PI / 180;
  }

  function set_checkpoints(lat, lon) {
    var bearing_rad,
      lat_end,
      lon_end,
      lat_start = to_rad(lat),
      lon_start = to_rad(lon),
      relative_d;

    DIRECTION_LIST.forEach(function (e) {
      bearing_rad = to_rad(e.bearing);
      relative_d = e.distance / R;

      lat_end = Math.asin(Math.sin(lat_start) * Math.cos(relative_d) +
        Math.cos(lat_start) * Math.sin(relative_d) * Math.cos(bearing_rad));
      lon_end = lon_start + Math.atan2(
        Math.sin(bearing_rad) * Math.sin(relative_d) * Math.cos(lat_start),
        Math.cos(relative_d) - Math.sin(lat_start) * Math.sin(lon_start));

      CHECKPOINT_LIST.push({
        latitude: to_deg(lat_end),
        longitude: to_deg(lon_end)
      });

      lat_start = lat_end;
      lon_start = lon_end;
    });
  }

  function distance(lat1, lon1, lat2, lon2) {
    var la1 = lat1 * Math.PI / 180, // lat, lon in radians
      la2 = lat2 * Math.PI / 180,
      lo1 = lon1 * Math.PI / 180,
      lo2 = lon2 * Math.PI / 180,
      haversine_phi = Math.pow(Math.sin((la2 - la1) / 2), 2),
      sin_lon = Math.sin((lo2 - lo1) / 2),
      h = haversine_phi + Math.cos(la1) * Math.cos(la2) * sin_lon * sin_lon;
    return 2 * R * Math.asin(Math.sqrt(h));
  }

  me.onStart = function (timestamp) {
    me.direction_set = false;
    me.next_checkpoint = 0;
    me.takeOff();
  };

  me.onUpdate = function (timestamp) {
    if (!me.isReadyToFly()) {
      return;
    }

    me.current_position = me.getCurrentPosition();
    if (CHECKPOINT_LIST.length === 0) {
      set_checkpoints(me.current_position.latitude,
                      me.current_position.longitude);
    }

    if (!me.direction_set) {
      if (me.next_checkpoint < CHECKPOINT_LIST.length) {
        me.setTargetCoordinates(
          CHECKPOINT_LIST[me.next_checkpoint].latitude,
          CHECKPOINT_LIST[me.next_checkpoint].longitude,
          ALTITUDE + ALTITUDE * me.id,
          5
        );
        console.log("[DEMO] Going to Checkpoint", me.next_checkpoint);
      }
      me.direction_set = true;
      return;
    }

    if (me.next_checkpoint < CHECKPOINT_LIST.length) {
      me.current_position = me.getCurrentPosition();
      me.distance = distance(
        me.current_position.latitude,
        me.current_position.longitude,
        CHECKPOINT_LIST[me.next_checkpoint].latitude,
        CHECKPOINT_LIST[me.next_checkpoint].longitude
      );
      if (me.distance <= EPSILON) {
        console.log("[DEMO] Reached Checkpoint %d", me.next_checkpoint);
        me.next_checkpoint += 1;
        me.direction_set = false;
      }
      return;
    }

    if (!me.isLanding()) {
      me.land();
    }
    if (me.getCurrentPosition().altitude <= 0) {
      me.exit(0);
    }
  };
}(console, me));