import defined from "../../Core/defined.js";
import destroyObject from "../../Core/destroyObject.js";
import DeveloperError from "../../Core/DeveloperError.js";
import EventHelper from "../../Core/EventHelper.js";
import OrthographicFrustum from "../../Core/OrthographicFrustum.js";
import SceneMode from "../../Scene/SceneMode.js";
import knockout from "../../ThirdParty/knockout.js";
import createCommand from "../createCommand.js";

/**
 * The view model for {@link ProjectionPicker}.
 * @alias ProjectionPickerViewModel
 * @constructor
 *
 * @param {Scene} scene The Scene to switch projections.
 */
function ProjectionPickerViewModel(scene) {
  //>>includeStart('debug', pragmas.debug);
  if (!defined(scene)) {
    throw new DeveloperError("scene is required.");
  }
  //>>includeEnd('debug');

  this._scene = scene;
  this._orthographic = scene.camera.frustum instanceof OrthographicFrustum;
  this._flightInProgress = false;

  /**
   * Gets or sets whether the button drop-down is currently visible.  This property is observable.
   * @type {Boolean}
   * @default false
   */
  this.dropDownVisible = false;

  /**
   * Gets or sets the perspective projection tooltip.  This property is observable.
   * @type {String}
   * @default 'Perspective Projection'
   */
  this.tooltipPerspective = "Perspective Projection";

  /**
   * Gets or sets the orthographic projection tooltip.  This property is observable.
   * @type {String}
   * @default 'Orthographic Projection'
   */
  this.tooltipOrthographic = "Orthographic Projection";

  /**
   * Gets the currently active tooltip.  This property is observable.
   * @type {String}
   */
  this.selectedTooltip = undefined;

  /**
   * Gets or sets the current SceneMode.  This property is observable.
   * @type {SceneMode}
   */
  this.sceneMode = scene.mode;

  knockout.track(this, [
    "_orthographic",
    "_flightInProgress",
    "sceneMode",
    "dropDownVisible",
    "tooltipPerspective",
    "tooltipOrthographic",
  ]);

  var that = this;
  knockout.defineProperty(this, "selectedTooltip", function () {
    if (that._orthographic) {
      return that.tooltipOrthographic;
    }
    return that.tooltipPerspective;
  });

  this._toggleDropDown = createCommand(function () {
    if (that.sceneMode === SceneMode.SCENE2D || that._flightInProgress) {
      return;
    }

    that.dropDownVisible = !that.dropDownVisible;
  });

  this._eventHelper = new EventHelper();
  this._eventHelper.add(scene.morphComplete, function (
    transitioner,
    oldMode,
    newMode,
    isMorphing
  ) {
    that.sceneMode = newMode;
    that._orthographic =
      newMode === SceneMode.SCENE2D ||
      that._scene.camera.frustum instanceof OrthographicFrustum;
  });
  this._eventHelper.add(scene.preRender, function () {
    that._flightInProgress = defined(scene.camera._currentFlight);
  });

  this._switchToPerspective = createCommand(function () {
    if (that.sceneMode === SceneMode.SCENE2D) {
      return;
    }

    that._scene.camera.switchToPerspectiveFrustum();
    that._orthographic = false;
    that.dropDownVisible = false;
  });

  this._switchToOrthographic = createCommand(function () {
    if (that.sceneMode === SceneMode.SCENE2D) {
      return;
    }

    that._scene.camera.switchToOrthographicFrustum();
    that._orthographic = true;
    that.dropDownVisible = false;
  });

  //Used by knockout
  this._sceneMode = SceneMode;
}

Object.defineProperties(ProjectionPickerViewModel.prototype, {
  /**
   * Gets the scene
   * @memberof ProjectionPickerViewModel.prototype
   * @type {Scene}
   */
  scene: {
    get: function () {
      return this._scene;
    },
  },

  /**
   * Gets the command to toggle the drop down box.
   * @memberof ProjectionPickerViewModel.prototype
   *
   * @type {Command}
   */
  toggleDropDown: {
    get: function () {
      return this._toggleDropDown;
    },
  },

  /**
   * Gets the command to switch to a perspective projection.
   * @memberof ProjectionPickerViewModel.prototype
   *
   * @type {Command}
   */
  switchToPerspective: {
    get: function () {
      return this._switchToPerspective;
    },
  },

  /**
   * Gets the command to switch to orthographic projection.
   * @memberof ProjectionPickerViewModel.prototype
   *
   * @type {Command}
   */
  switchToOrthographic: {
    get: function () {
      return this._switchToOrthographic;
    },
  },

  /**
   * Gets whether the scene is currently using an orthographic projection.
   * @memberof ProjectionPickerViewModel.prototype
   *
   * @type {Command}
   */
  isOrthographicProjection: {
    get: function () {
      return this._orthographic;
    },
  },
});

/**
 * @returns {Boolean} true if the object has been destroyed, false otherwise.
 */
ProjectionPickerViewModel.prototype.isDestroyed = function () {
  return false;
};

/**
 * Destroys the view model.
 */
ProjectionPickerViewModel.prototype.destroy = function () {
  this._eventHelper.removeAll();
  destroyObject(this);
};
export default ProjectionPickerViewModel;
