'use strict';

function sensor_mocks(mojo) {
  return define('Generic Sensor API mocks', [
    'mojo/public/js/core',
    'mojo/public/js/bindings',
    'mojo/public/js/connection',
    'device/generic_sensor/public/interfaces/sensor_provider.mojom',
    'device/generic_sensor/public/interfaces/sensor.mojom',
  ], (core, bindings, connection, sensor_provider, sensor) => {

    // Helper function that returns resolved promise with result.
    function sensorResponse(success) {
      return Promise.resolve({success});
    }

    // Class that mocks Sensor interface defined in sensor.mojom
    class MockSensor {
      constructor(stub, handle, offset, size, reportingMode) {
        this.client_ = null;
        this.stub_ = stub;
        this.start_should_fail_ = false;
        this.reporting_mode_ = reportingMode;
        this.sensor_reading_timer_id_ = null;
        this.update_reading_function_ = null;
        this.suspend_called_ = null;
        this.resume_called_ = null;
        this.add_configuration_called_ = null;
        this.remove_configuration_called_ = null;
        this.active_sensor_configurations_ = [];
        let rv = core.mapBuffer(handle, offset, size,
            core.MAP_BUFFER_FLAG_NONE);
        assert_equals(rv.result, core.RESULT_OK, "Failed to map shared buffer");
        this.buffer_array_ = rv.buffer;
        this.buffer_ = new Float64Array(this.buffer_array_);
        bindings.StubBindings(this.stub_).delegate = this;
        bindings.StubBindings(this.stub_).connectionErrorHandler = () => {
          reset();
        };
      }

      // Returns default configuration.
      getDefaultConfiguration() {
        return Promise.resolve({frequency: 5});
      }

      // Adds configuration for the sensor and starts reporting fake data
      // through update_reading_function_ callback.
      addConfiguration(configuration) {
        assert_not_equals(configuration, null, "Invalid sensor configuration.");

        if (this.add_configuration_called_ != null) {
          this.add_configuration_called_(this);
        }

        if (!this.start_should_fail_ && this.update_reading_function_ != null) {
          let timeout = (1 / configuration.frequency) * 1000;
          this.sensor_reading_timer_id_ = window.setTimeout(() => {
            this.update_reading_function_(this.buffer_);
            if (this.reporting_mode_ === sensor.ReportingMode.ON_CHANGE) {
              this.client_.sensorReadingChanged();
            }
          }, timeout);

          this.active_sensor_configurations_.push(configuration);
        }

        return sensorResponse(!this.start_should_fail_);
      }

      // Removes sensor configuration from the list of active configurations and
      // stops notification about sensor reading changes if
      // active_sensor_configurations_ is empty.
      removeConfiguration(configuration) {
        if (this.remove_configuration_called_ != null) {
          this.remove_configuration_called_(this);
        }

        let index = this.active_sensor_configurations_.indexOf(configuration);
        if (index !== -1) {
          this.active_sensor_configurations_.splice(index, 1);
        } else {
          return sensorResponse(false);
        }

        if (this.sensor_reading_timer_id_ != null
            && this.active_sensor_configurations_.length === 0) {
          window.clearTimeout(this.sensor_reading_timer_id_);
          this.sensor_reading_timer_id_ = null;
        }

        return sensorResponse(true);
      }

      // Suspends sensor.
      suspend() {
        if (this.suspend_called_ != null) {
          this.suspend_called_(this);
        }
      }

      // Resumes sensor.
      resume() {
        if (this.resume_called_ != null) {
          this.resume_called_(this);
        }
      }

      // Mock functions

      // Resets mock Sensor state.
      reset() {
        if (this.sensor_reading_timer_id_) {
          window.clearTimeout(this.sensor_reading_timer_id_);
        }

        this.start_should_fail_ = false;
        this.sensor_reading_timer_id_ = null;
        this.active_sensor_configurations_ = [];
        this.suspend_called_ = null;
        this.resume_called_ = null;
        this.add_configuration_called_ = null;
        this.remove_configuration_called_ = null;
        for (let i = 0; i < this.buffer_.length; ++i) {
          this.buffer_[i] = 0;
        }
      }

      // Sets callback that is used to deliver sensor reading updates.
      setUpdateSensorReadingFunction(update_reading_function) {
        this.update_reading_function_ = update_reading_function;
        return Promise.resolve(this);
      }

      // Sets flag that forces sensor to fail when addConfiguration is invoked.
      setStartShouldFail(should_fail) {
        this.start_should_fail_ = should_fail;
      }

      // Returns resolved promise if suspend() was called, rejected otherwise.
      suspendCalled() {
        return new Promise((resolve, reject) => {
          this.suspend_called_ = resolve;
        });
      }

      // Returns resolved promise if resume() was called, rejected otherwise.
      resumeCalled() {
        return new Promise((resolve, reject) => {
          this.resume_called_ = resolve;
        });
      }

      // Resolves promise when addConfiguration() is called.
      addConfigurationCalled() {
        return new Promise((resolve, reject) => {
          this.add_configuration_called_ = resolve;
        });
      }

      // Resolves promise when removeConfiguration() is called.
      removeConfigurationCalled() {
        return new Promise((resolve, reject) => {
          this.remove_configuration_called_ = resolve;
        });
      }

    }

    // Helper function that returns resolved promise for getSensor() function.
    function getSensorResponse(init_params, client_request) {
      return Promise.resolve({init_params, client_request});
    }

    // Class that mocks SensorProvider interface defined in
    // sensor_provider.mojom
    class MockSensorProvider {
      constructor() {
        this.reading_size_in_bytes_ =
            sensor_provider.SensorInitParams.kReadBufferSize;
        this.shared_buffer_size_in_bytes_ = this.reading_size_in_bytes_ *
                sensor.SensorType.LAST;
        let rv =
                core.createSharedBuffer(
                        this.shared_buffer_size_in_bytes_,
                        core.CREATE_SHARED_BUFFER_OPTIONS_FLAG_NONE);
        assert_equals(rv.result, core.RESULT_OK, "Failed to create buffer");
        this.shared_buffer_handle_ = rv.handle;
        this.active_sensor_ = null;
        this.get_sensor_should_fail_ = false;
        this.resolve_func_ = null;
        this.is_continuous_ = false;
      }

      // Returns initialized Sensor proxy to the client.
      getSensor(type, stub) {
        if (this.get_sensor_should_fail_) {
          return getSensorResponse(null, null);
        }

        let offset =
                (sensor.SensorType.LAST - type) * this.reading_size_in_bytes_;
        let reporting_mode = sensor.ReportingMode.ON_CHANGE;
        if (this.is_continuous_) {
            reporting_mode = sensor.ReportingMode.CONTINUOUS;
        }

        if (this.active_sensor_ == null) {
          let mockSensor = new MockSensor(stub, this.shared_buffer_handle_,
              offset, this.reading_size_in_bytes_, reporting_mode);
          this.active_sensor_ = mockSensor;
        }

        let rv =
                core.duplicateBufferHandle(
                        this.shared_buffer_handle_,
                        core.DUPLICATE_BUFFER_HANDLE_OPTIONS_FLAG_NONE);

        assert_equals(rv.result, core.RESULT_OK);

        let default_config = {frequency: 5};

        let init_params =
            new sensor_provider.SensorInitParams(
                { memory: rv.handle,
                  buffer_offset: offset,
                  mode: reporting_mode,
                  default_configuration: default_config });

        if (this.resolve_func_ !== null) {
          this.resolve_func_(this.active_sensor_);
        }

        var client_handle = connection.bindProxy(proxy => {
          this.active_sensor_.client_ = proxy;
          }, sensor.SensorClient);

        return getSensorResponse(init_params, client_handle);
      }

      // Binds object to mojo message pipe
      bindToPipe(pipe) {
        this.stub_ = connection.bindHandleToStub(
            pipe, sensor_provider.SensorProvider);
        bindings.StubBindings(this.stub_).delegate = this;
      }

      // Mock functions

      // Resets state of mock SensorProvider between test runs.
      reset() {
        if (this.active_sensor_ != null) {
          this.active_sensor_.reset();
        }

        this.get_sensor_should_fail_ = false;
        this.resolve_func_ = null;
      }

      // Sets flag that forces mock SensorProvider to fail when getSensor() is
      // invoked.
      setGetSensorShouldFail(should_fail) {
        this.get_sensor_should_fail_ = should_fail;
      }

      // Returns mock sensor that was created in getSensor to the layout test.
      getCreatedSensor() {
        if (this.active_sensor_ != null) {
          return Promise.resolve(this.active_sensor_);
        }

        return new Promise((resolve, reject) => {
          this.resolve_func_ = resolve;
         });
      }

      // Forces sensor to use |reporting_mode| as an update mode.
      setContinuousReportingMode(reporting_mode) {
          this.is_continuous_ = reporting_mode;
      }
    }

    let mockSensorProvider = new MockSensorProvider;
    mojo.frameInterfaces.addInterfaceOverrideForTesting(
        sensor_provider.SensorProvider.name,
        pipe => {
          mockSensorProvider.bindToPipe(pipe);
        });

    return Promise.resolve({
      mockSensorProvider: mockSensorProvider,
    });
  });
}

function sensor_test(func, name, properties) {
  mojo_test(mojo => sensor_mocks(mojo).then(sensor => {
    let result = Promise.resolve(func(sensor));
    let cleanUp = () => { sensor.mockSensorProvider.reset(); };
    return result.then(cleanUp, cleanUp);
  }), name, properties);
}
