var assert = chai.assert;

describe("'Canary' checks", function() {
  this.timeout(testconfig.timeouts.standard);

  before(function() {
    fixture.setBase('');
  })

  it('host-fixture.html + gestureHost.css', function() {
    let element = fixture.load('host-fixture.html')[0];

    // Ensure that not only did we get an element, we got the expected element.
    assert.isNotNull(element);
    assert.isDefined(element);
    assert.equal(element.id, 'host-fixture');
    // If the CSS is missing, the element will default to zero height.
    assert.notEqual(element.getBoundingClientRect().height, 0);
  });

  it('canaryRecording.json', function() {
    let jsonObject = window['__json__'].canaryRecording;

    assert.isNotNull(jsonObject);
    assert.isDefined(jsonObject);

    let config = new Testing.FixtureLayoutConfiguration(jsonObject.config);
    assert.equal(config.deviceStyle, 'screen4');
  });

  it('Testing.HostFixtureLayoutController', function(done) {
    let targetRoot = fixture.load('host-fixture.html')[0];
    let jsonObject = window['__json__'].canaryRecording;

    let controller = new Testing.HostFixtureLayoutController();
    // Note:  this is set BEFORE the controller is configured (in the following line).
    // The class is designed to support this.
    controller.layoutConfiguration = new Testing.FixtureLayoutConfiguration(jsonObject.config);
    controller.connect().then(() => {
      assert.isTrue(targetRoot.className.indexOf('screen4') > -1, "Could not apply configuration spec from recorded JSON!");
      done();
    }).finally(() => controller.destroy());
  })

  afterEach(function() {
    fixture.cleanup();
  })

  describe('event simulation', function() {
    beforeEach(function(done) {
      fixture.load('host-fixture.html');
      this.controller = new Testing.HostFixtureLayoutController();
      this.controller.connect().then(() => done());
    });

    afterEach(function() {
      this.controller.destroy();
      fixture.cleanup();
    });

    it("InputSequenceSimulator.replayTouchSample", function() {
      let playbackEngine = new Testing.InputSequenceSimulator(this.controller);
      let layout = new Testing.FixtureLayoutConfiguration("screen2", "bounds1", "full", "safe-loose");
      this.controller.layoutConfiguration = layout;

      let fireEvent = () => {
        playbackEngine.replayTouchSample(/*relative coord:*/ {targetX: 10, targetY: 10},
                                          /*state:*/         "start",
                                          /*identifier:*/    1,
                                          /*otherTouches:*/  [],
                                        );
      }

      // Ensure that the expected handler is called.
      let proto = com.keyman.osk.TouchEventEngine.prototype;
      let trueHandler = proto.onTouchStart;
      let fakeHandler = proto.onTouchStart = sinon.fake();
      fireEvent();
      try {
        assert.isTrue(fakeHandler.called, "Unit test attempt failed:  handler was not called successfully.");
      } finally {
        // Restore the true implementation.
        proto.onTouchStart = trueHandler;
      }
    });

    it("InputSequenceSimulator.replayMouseSample", function() {
      let playbackEngine = new Testing.InputSequenceSimulator(this.controller);
      let layout = new Testing.FixtureLayoutConfiguration("screen2", "bounds1", "full", "safe-loose");
      this.controller.layoutConfiguration = layout;

      let fireEvent = () => {
        playbackEngine.replayMouseSample(/*relative coord:*/ {targetX: 15, targetY: 15},
                                          /*state:*/         "start"
                                        );
      }

      // Ensure that the expected handler is called.
      let proto = com.keyman.osk.MouseEventEngine.prototype;
      let trueHandler = proto.onMouseStart;
      let fakeHandler = proto.onMouseStart = sinon.fake();
      fireEvent();
      try {
        assert.isTrue(fakeHandler.called, "Unit test attempt failed:  handler was not called successfully.");
      } finally {
        // Restore the true implementation.
        proto.onMouseStart = trueHandler;
      }
    });
  });
});