define([
  "dojo/_base/declare",
  "dojo/topic",
  "CesiumAdaptor/CesiumViewer"
], function (declare, topic, CesiumViewer) {

  return declare(null, {

    constructor: function () {
      this.mouseClicks = 0;
      this.lons = [];
      this.lats = [];
      this.bindedClickHandler = this.clickHandler.bind(this);
      this.bindedMoveHandler = this.moveHandler.bind(this);
      this.bindedDynaimcPropertyHandler = this.dynamicPropertyHandler.bind(this);

      this.rectangle = new Cesium.Rectangle();
      this.firstCartographic = {};

    },

    register: function () {
      let viewer = CesiumViewer.getViewer();
      viewer.scene.canvas.addEventListener('click', this.bindedClickHandler);

    },

    unregister: function () {
      let viewer = CesiumViewer.getViewer();
      viewer.scene.canvas.removeEventListener('click', this.bindedClickHandler);
    },

    create: function () {
      this.lons = [];
      this.lats = [];
    },

    clear: function () {
      this.mouseClicks = 0;
      this.lons = [];
      this.lats = [];

      let viewer = CesiumViewer.getViewer();
      viewer.entities.removeById("bb");
      this.rectangle = new Cesium.Rectangle();
    },

    clickHandler: function (event) {

      let viewer = CesiumViewer.getViewer();
      this.mouseClicks++;
      let mousePosition = new Cesium.Cartesian2(event.layerX, event.layerY);
      let ellipsoid = viewer.scene.globe.ellipsoid;
      let cartesian = viewer.camera.pickEllipsoid(mousePosition, ellipsoid);
      if (!cartesian) { return; }
      let cartographic = ellipsoid.cartesianToCartographic(cartesian);
      let longitudeString = Cesium.Math.toDegrees(cartographic.longitude).toFixed(10);
      let latitudeString = Cesium.Math.toDegrees(cartographic.latitude).toFixed(10);
      this.lons.push(parseFloat(longitudeString));
      this.lats.push(parseFloat(latitudeString));

      if (this.mouseClicks == 1) {
        this.firstCartographic = cartographic;
        viewer.entities.add({
          id: "bb",
          rectangle: {
            coordinates: new Cesium.CallbackProperty(this.bindedDynaimcPropertyHandler, false),
            material: Cesium.Color.BLUE.withAlpha(0.2)
          }
        });
        viewer.scene.canvas.addEventListener('mousemove', this.bindedMoveHandler);
      }

      if (this.mouseClicks == 2) {
        viewer.scene.canvas.removeEventListener('mousemove', this.bindedMoveHandler);
        this.lons = this.lons.sort(function (a, b) { return a - b; });
        this.lats = this.lats.sort(function (a, b) { return a - b; });
        topic.publish("BoundingBoxCreated", "BoundingBoxDefined");
      }

    },

    moveHandler: function (event) {

      let viewer = CesiumViewer.getViewer();
      let mousePosition = new Cesium.Cartesian2(event.layerX, event.layerY);
      let ellipsoid = viewer.scene.globe.ellipsoid;
      let cartesian = viewer.camera.pickEllipsoid(mousePosition, ellipsoid);
      if (!cartesian) { return; }
      let secondCartographic = ellipsoid.cartesianToCartographic(cartesian);
      this.rectangle.east = Math.max(secondCartographic.longitude, this.firstCartographic.longitude);
      this.rectangle.west = Math.min(secondCartographic.longitude, this.firstCartographic.longitude);
      this.rectangle.north = Math.max(secondCartographic.latitude, this.firstCartographic.latitude);
      this.rectangle.south = Math.min(secondCartographic.latitude, this.firstCartographic.latitude);
    },

    dynamicPropertyHandler: function (time, result) {

      return Cesium.Rectangle.clone(this.rectangle, result);
    },

    toString: function () {
      return this.lons[0] + "," + this.lats[0] + "," + this.lons[1] + "," + this.lats[1];
    }

  });

});