import { Cartesian3 } from "../../Source/Cesium.js";
import { Math as CesiumMath } from "../../Source/Cesium.js";
import { DeviceOrientationCameraController } from "../../Source/Cesium.js";
import createCamera from "../createCamera.js";
import createCanvas from "../createCanvas.js";
import DomEventSimulator from "../DomEventSimulator.js";

describe("Scene/DeviceOrientationCameraController", function () {
  var scene;
  var canvas;
  var camera;
  var controller;

  function MockScene(canvas, camera) {
    this.canvas = canvas;
    this.camera = camera;
  }

  beforeAll(function () {
    canvas = createCanvas();
  });

  afterAll(function () {
    document.body.removeChild(canvas);
  });

  beforeEach(function () {
    camera = createCamera({
      canvas: canvas,
      offset: new Cartesian3(-1.0, 0.0, 0.0),
    });
    scene = new MockScene(canvas, camera);
    controller = new DeviceOrientationCameraController(scene);
  });

  afterEach(function () {
    controller =
      controller && !controller.isDestroyed() && controller.destroy();
  });

  function fireEvent(options) {
    // set default orientation
    DomEventSimulator.fireDeviceOrientation(window);
    controller.update();
    // update delta orientation
    DomEventSimulator.fireDeviceOrientation(window, options);
    controller.update();
  }

  it("throws without scene", function () {
    expect(function () {
      return new DeviceOrientationCameraController();
    }).toThrowDeveloperError();
  });

  it("rotates for alpha", function () {
    var position = Cartesian3.clone(camera.position);
    var up = Cartesian3.clone(camera.up);

    fireEvent({
      alpha: 90.0,
    });

    expect(camera.position).toEqual(position);
    expect(camera.direction).toEqualEpsilon(
      Cartesian3.UNIT_Y,
      CesiumMath.EPSILON14
    );
    expect(camera.up).toEqualEpsilon(up, CesiumMath.EPSILON14);
    expect(camera.right).toEqualEpsilon(
      Cartesian3.UNIT_X,
      CesiumMath.EPSILON14
    );
  });

  it("rotates for beta", function () {
    var position = Cartesian3.clone(camera.position);
    var direction = Cartesian3.clone(camera.direction);

    fireEvent({
      beta: 90.0,
    });

    expect(camera.position).toEqual(position);
    expect(camera.direction).toEqualEpsilon(direction, CesiumMath.EPSILON14);
    expect(camera.up).toEqualEpsilon(Cartesian3.UNIT_Y, CesiumMath.EPSILON14);
    expect(camera.right).toEqualEpsilon(
      Cartesian3.UNIT_Z,
      CesiumMath.EPSILON14
    );
  });

  it("rotates for gamma", function () {
    var position = Cartesian3.clone(camera.position);
    var right = Cartesian3.clone(camera.right);

    fireEvent({
      gamma: 90.0,
    });

    expect(camera.position).toEqual(position);
    expect(camera.direction).toEqualEpsilon(
      Cartesian3.negate(Cartesian3.UNIT_Z, new Cartesian3()),
      CesiumMath.EPSILON14
    );
    expect(camera.up).toEqualEpsilon(Cartesian3.UNIT_X, CesiumMath.EPSILON14);
    expect(camera.right).toEqualEpsilon(right, CesiumMath.EPSILON14);
  });

  it("is destroyed", function () {
    expect(controller.isDestroyed()).toEqual(false);
    controller.destroy();
    expect(controller.isDestroyed()).toEqual(true);
  });
});
