// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <memory>

#include "base/bind_helpers.h"
#include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "base/memory/ref_counted.h"
#include "mojo/public/cpp/bindings/binding.h"
#include "services/device/device_service_test_base.h"
#include "services/device/generic_sensor/absolute_orientation_euler_angles_fusion_algorithm_using_accelerometer_and_magnetometer.h"
#include "services/device/generic_sensor/fake_platform_sensor_and_provider.h"
#include "services/device/generic_sensor/linear_acceleration_fusion_algorithm_using_accelerometer.h"
#include "services/device/generic_sensor/platform_sensor.h"
#include "services/device/generic_sensor/platform_sensor_fusion.h"
#include "services/device/generic_sensor/platform_sensor_provider.h"
#include "testing/gtest/include/gtest/gtest.h"

using ::testing::_;
using ::testing::Invoke;
using ::testing::Return;

namespace device {

using mojom::SensorType;

class PlatformSensorFusionTest : public DeviceServiceTestBase {
 public:
  PlatformSensorFusionTest() {
    provider_ = std::make_unique<FakePlatformSensorProvider>();
    PlatformSensorProvider::SetProviderForTesting(provider_.get());
  }

 protected:
  void AccelerometerCallback(scoped_refptr<PlatformSensor> sensor) {
    accelerometer_callback_called_ = true;
    accelerometer_ = static_cast<FakePlatformSensor*>(sensor.get());
  }

  void MagnetometerCallback(scoped_refptr<PlatformSensor> sensor) {
    magnetometer_callback_called_ = true;
    magnetometer_ = static_cast<FakePlatformSensor*>(sensor.get());
  }

  void PlatformSensorFusionCallback(scoped_refptr<PlatformSensor> sensor) {
    platform_sensor_fusion_callback_called_ = true;
    fusion_sensor_ = static_cast<PlatformSensorFusion*>(sensor.get());
  }

  void CreateAccelerometer() {
    auto callback = base::Bind(&PlatformSensorFusionTest::AccelerometerCallback,
                               base::Unretained(this));
    provider_->CreateSensor(SensorType::ACCELEROMETER, callback);
    EXPECT_TRUE(accelerometer_callback_called_);
    EXPECT_TRUE(accelerometer_);
    EXPECT_EQ(SensorType::ACCELEROMETER, accelerometer_->GetType());
  }

  void CreateMagnetometer() {
    auto callback = base::Bind(&PlatformSensorFusionTest::MagnetometerCallback,
                               base::Unretained(this));
    provider_->CreateSensor(SensorType::MAGNETOMETER, callback);
    EXPECT_TRUE(magnetometer_callback_called_);
    EXPECT_TRUE(magnetometer_);
    EXPECT_EQ(SensorType::MAGNETOMETER, magnetometer_->GetType());
  }

  void CreateLinearAccelerationFusionSensor() {
    auto fusion_algorithm =
        std::make_unique<LinearAccelerationFusionAlgorithmUsingAccelerometer>();
    CreateFusionSensor(std::move(fusion_algorithm));
  }

  void CreateAbsoluteOrientationEulerAnglesFusionSensor() {
    auto fusion_algorithm = std::make_unique<
        AbsoluteOrientationEulerAnglesFusionAlgorithmUsingAccelerometerAndMagnetometer>();
    CreateFusionSensor(std::move(fusion_algorithm));
  }

  void CreateFusionSensor(
      std::unique_ptr<PlatformSensorFusionAlgorithm> fusion_algorithm) {
    auto callback =
        base::Bind(&PlatformSensorFusionTest::PlatformSensorFusionCallback,
                   base::Unretained(this));
    SensorType type = fusion_algorithm->fused_type();
    PlatformSensorFusion::Create(provider_->GetSensorReadingBuffer(type),
                                 provider_.get(), std::move(fusion_algorithm),
                                 callback);
    EXPECT_TRUE(platform_sensor_fusion_callback_called_);
  }

  std::unique_ptr<FakePlatformSensorProvider> provider_;
  bool accelerometer_callback_called_ = false;
  scoped_refptr<FakePlatformSensor> accelerometer_;
  bool magnetometer_callback_called_ = false;
  scoped_refptr<FakePlatformSensor> magnetometer_;
  bool platform_sensor_fusion_callback_called_ = false;
  scoped_refptr<PlatformSensorFusion> fusion_sensor_;

 private:
  DISALLOW_COPY_AND_ASSIGN(PlatformSensorFusionTest);
};

// The following code tests creating a fusion sensor that needs one source
// sensor.

TEST_F(PlatformSensorFusionTest, SourceSensorAlreadyExists) {
  EXPECT_FALSE(provider_->GetSensor(SensorType::ACCELEROMETER));
  CreateAccelerometer();
  // Now the source sensor already exists.
  EXPECT_TRUE(provider_->GetSensor(SensorType::ACCELEROMETER));

  CreateLinearAccelerationFusionSensor();
  EXPECT_TRUE(fusion_sensor_);
  EXPECT_EQ(SensorType::LINEAR_ACCELERATION, fusion_sensor_->GetType());
}

TEST_F(PlatformSensorFusionTest, SourceSensorWorksSeparately) {
  CreateAccelerometer();
  EXPECT_TRUE(accelerometer_);
  EXPECT_FALSE(accelerometer_->IsActiveForTesting());

  auto client = std::make_unique<testing::NiceMock<MockPlatformSensorClient>>();
  accelerometer_->AddClient(client.get());
  accelerometer_->StartListening(client.get(), PlatformSensorConfiguration(10));
  EXPECT_TRUE(accelerometer_->IsActiveForTesting());

  CreateLinearAccelerationFusionSensor();
  EXPECT_TRUE(fusion_sensor_);
  EXPECT_EQ(SensorType::LINEAR_ACCELERATION, fusion_sensor_->GetType());
  EXPECT_FALSE(fusion_sensor_->IsActiveForTesting());

  fusion_sensor_->AddClient(client.get());
  fusion_sensor_->StartListening(client.get(), PlatformSensorConfiguration(10));
  EXPECT_TRUE(fusion_sensor_->IsActiveForTesting());

  fusion_sensor_->StopListening(client.get(), PlatformSensorConfiguration(10));
  EXPECT_FALSE(fusion_sensor_->IsActiveForTesting());

  EXPECT_TRUE(accelerometer_->IsActiveForTesting());

  accelerometer_->RemoveClient(client.get());
  EXPECT_FALSE(accelerometer_->IsActiveForTesting());

  fusion_sensor_->RemoveClient(client.get());
}

namespace {

void CheckConfigsCountForClient(const scoped_refptr<PlatformSensor>& sensor,
                                PlatformSensor::Client* client,
                                size_t expected_count) {
  auto client_entry = sensor->GetConfigMapForTesting().find(client);
  if (sensor->GetConfigMapForTesting().end() == client_entry) {
    EXPECT_EQ(0u, expected_count);
    return;
  }
  EXPECT_EQ(expected_count, client_entry->second.size());
}

}  // namespace

TEST_F(PlatformSensorFusionTest, SourceSensorDoesNotKeepOutdatedConfigs) {
  CreateAccelerometer();
  EXPECT_TRUE(accelerometer_);

  CreateLinearAccelerationFusionSensor();
  EXPECT_TRUE(fusion_sensor_);
  EXPECT_EQ(SensorType::LINEAR_ACCELERATION, fusion_sensor_->GetType());

  auto client = std::make_unique<testing::NiceMock<MockPlatformSensorClient>>(
      fusion_sensor_);
  fusion_sensor_->StartListening(client.get(), PlatformSensorConfiguration(10));
  fusion_sensor_->StartListening(client.get(), PlatformSensorConfiguration(20));
  fusion_sensor_->StartListening(client.get(), PlatformSensorConfiguration(30));

  EXPECT_EQ(1u, fusion_sensor_->GetConfigMapForTesting().size());
  EXPECT_EQ(1u, accelerometer_->GetConfigMapForTesting().size());

  CheckConfigsCountForClient(fusion_sensor_, client.get(), 3u);
  // Fusion sensor is a client for its sources, however it must keep only
  // one active configuration for them at a time.
  CheckConfigsCountForClient(accelerometer_, fusion_sensor_.get(), 1u);

  fusion_sensor_->StopListening(client.get(), PlatformSensorConfiguration(30));
  fusion_sensor_->StopListening(client.get(), PlatformSensorConfiguration(20));

  CheckConfigsCountForClient(fusion_sensor_, client.get(), 1u);
  CheckConfigsCountForClient(accelerometer_, fusion_sensor_.get(), 1u);

  fusion_sensor_->StopListening(client.get(), PlatformSensorConfiguration(10));

  CheckConfigsCountForClient(fusion_sensor_, client.get(), 0u);
  CheckConfigsCountForClient(accelerometer_, fusion_sensor_.get(), 0u);
}

TEST_F(PlatformSensorFusionTest, AllSourceSensorsStoppedOnSingleSourceFailure) {
  CreateAccelerometer();
  EXPECT_TRUE(accelerometer_);

  CreateMagnetometer();
  EXPECT_TRUE(magnetometer_);
  // Magnetometer will be started after Accelerometer for the given
  // sensor fusion algorithm.
  ON_CALL(*magnetometer_, StartSensor(_)).WillByDefault(Return(false));

  CreateAbsoluteOrientationEulerAnglesFusionSensor();
  EXPECT_TRUE(fusion_sensor_);
  EXPECT_EQ(SensorType::ABSOLUTE_ORIENTATION_EULER_ANGLES,
            fusion_sensor_->GetType());

  auto client = std::make_unique<testing::NiceMock<MockPlatformSensorClient>>(
      fusion_sensor_);
  fusion_sensor_->StartListening(client.get(), PlatformSensorConfiguration(10));

  EXPECT_FALSE(fusion_sensor_->IsActiveForTesting());
  EXPECT_FALSE(accelerometer_->IsActiveForTesting());
  EXPECT_FALSE(magnetometer_->IsActiveForTesting());
}

TEST_F(PlatformSensorFusionTest, SourceSensorNeedsToBeCreated) {
  EXPECT_FALSE(provider_->GetSensor(SensorType::ACCELEROMETER));

  CreateLinearAccelerationFusionSensor();
  EXPECT_TRUE(fusion_sensor_);
  EXPECT_EQ(SensorType::LINEAR_ACCELERATION, fusion_sensor_->GetType());
}

TEST_F(PlatformSensorFusionTest, SourceSensorIsNotAvailable) {
  // Accelerometer is not available.
  ON_CALL(*provider_, DoCreateSensorInternal(SensorType::ACCELEROMETER, _, _))
      .WillByDefault(Invoke(
          [](mojom::SensorType, scoped_refptr<PlatformSensor>,
             const FakePlatformSensorProvider::CreateSensorCallback& callback) {
            callback.Run(nullptr);
          }));

  CreateLinearAccelerationFusionSensor();
  EXPECT_FALSE(fusion_sensor_);
}

// The following code tests creating a fusion sensor that needs two source
// sensors.

TEST_F(PlatformSensorFusionTest, BothSourceSensorsAlreadyExist) {
  EXPECT_FALSE(provider_->GetSensor(SensorType::ACCELEROMETER));
  CreateAccelerometer();
  EXPECT_TRUE(provider_->GetSensor(SensorType::ACCELEROMETER));

  EXPECT_FALSE(provider_->GetSensor(SensorType::MAGNETOMETER));
  CreateMagnetometer();
  EXPECT_TRUE(provider_->GetSensor(SensorType::MAGNETOMETER));

  CreateAbsoluteOrientationEulerAnglesFusionSensor();
  EXPECT_TRUE(fusion_sensor_);
  EXPECT_EQ(SensorType::ABSOLUTE_ORIENTATION_EULER_ANGLES,
            fusion_sensor_->GetType());
}

TEST_F(PlatformSensorFusionTest, BothSourceSensorsNeedToBeCreated) {
  EXPECT_FALSE(provider_->GetSensor(SensorType::ACCELEROMETER));
  EXPECT_FALSE(provider_->GetSensor(SensorType::MAGNETOMETER));

  CreateAbsoluteOrientationEulerAnglesFusionSensor();
  EXPECT_TRUE(fusion_sensor_);
  EXPECT_EQ(SensorType::ABSOLUTE_ORIENTATION_EULER_ANGLES,
            fusion_sensor_->GetType());
}

TEST_F(PlatformSensorFusionTest, BothSourceSensorsAreNotAvailable) {
  // Failure.
  ON_CALL(*provider_, DoCreateSensorInternal(_, _, _))
      .WillByDefault(Invoke(
          [](mojom::SensorType, scoped_refptr<PlatformSensor>,
             const FakePlatformSensorProvider::CreateSensorCallback& callback) {
            callback.Run(nullptr);
          }));

  CreateAbsoluteOrientationEulerAnglesFusionSensor();
  EXPECT_FALSE(fusion_sensor_);
}

TEST_F(PlatformSensorFusionTest,
       OneSourceSensorAlreadyExistsTheOtherSourceSensorNeedsToBeCreated) {
  EXPECT_FALSE(provider_->GetSensor(SensorType::ACCELEROMETER));
  CreateAccelerometer();
  EXPECT_TRUE(provider_->GetSensor(SensorType::ACCELEROMETER));
  EXPECT_FALSE(provider_->GetSensor(SensorType::MAGNETOMETER));

  CreateAbsoluteOrientationEulerAnglesFusionSensor();
  EXPECT_TRUE(fusion_sensor_);
  EXPECT_EQ(SensorType::ABSOLUTE_ORIENTATION_EULER_ANGLES,
            fusion_sensor_->GetType());
}

TEST_F(PlatformSensorFusionTest,
       OneSourceSensorAlreadyExistsTheOtherSourceSensorIsNotAvailable) {
  EXPECT_FALSE(provider_->GetSensor(SensorType::ACCELEROMETER));
  CreateAccelerometer();
  EXPECT_TRUE(provider_->GetSensor(SensorType::ACCELEROMETER));

  // Magnetometer is not available.
  ON_CALL(*provider_, DoCreateSensorInternal(SensorType::MAGNETOMETER, _, _))
      .WillByDefault(Invoke(
          [](mojom::SensorType, scoped_refptr<PlatformSensor>,
             const FakePlatformSensorProvider::CreateSensorCallback& callback) {
            callback.Run(nullptr);
          }));

  CreateAbsoluteOrientationEulerAnglesFusionSensor();
  EXPECT_FALSE(fusion_sensor_);
}

TEST_F(PlatformSensorFusionTest,
       OneSourceSensorNeedsToBeCreatedTheOtherSourceSensorIsNotAvailable) {
  EXPECT_FALSE(provider_->GetSensor(SensorType::ACCELEROMETER));
  // Magnetometer is not available.
  ON_CALL(*provider_, DoCreateSensorInternal(SensorType::MAGNETOMETER, _, _))
      .WillByDefault(Invoke(
          [](mojom::SensorType, scoped_refptr<PlatformSensor>,
             const FakePlatformSensorProvider::CreateSensorCallback& callback) {
            callback.Run(nullptr);
          }));

  CreateAbsoluteOrientationEulerAnglesFusionSensor();
  EXPECT_FALSE(fusion_sensor_);
}

}  //  namespace device
