/*
 * Copyright 2019 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "os/repeating_alarm.h"

#include <future>

#include "common/bind.h"
#include "gtest/gtest.h"

namespace bluetooth {
namespace os {
namespace {

constexpr int error_ms = 20;

class RepeatingAlarmTest : public ::testing::Test {
 protected:
  void SetUp() override {
    thread_ = new Thread("test_thread", Thread::Priority::NORMAL);
    handler_ = new Handler(thread_);
    alarm_ = new RepeatingAlarm(handler_);
  }

  void TearDown() override {
    delete alarm_;
    handler_->Clear();
    delete handler_;
    delete thread_;
  }

  void VerifyMultipleDelayedTasks(int scheduled_tasks, int task_length_ms, int interval_between_tasks_ms) {
    std::promise<void> promise;
    auto future = promise.get_future();
    auto start_time = std::chrono::steady_clock::now();
    int counter = 0;
    alarm_->Schedule(
        common::Bind(
            &RepeatingAlarmTest::verify_delayed_tasks,
            common::Unretained(this),
            common::Unretained(&counter),
            start_time,
            scheduled_tasks,
            common::Unretained(&promise),
            task_length_ms,
            interval_between_tasks_ms),
        std::chrono::milliseconds(interval_between_tasks_ms));
    future.get();
    alarm_->Cancel();
  }

  void verify_delayed_tasks(
      int* counter,
      std::chrono::steady_clock::time_point start_time,
      int scheduled_tasks,
      std::promise<void>* promise,
      int task_length_ms,
      int interval_between_tasks_ms) {
    *counter = *counter + 1;
    auto time_now = std::chrono::steady_clock::now();
    auto time_delta = time_now - start_time;
    if (*counter == scheduled_tasks) {
      promise->set_value();
    }
    ASSERT_NEAR(time_delta.count(), interval_between_tasks_ms * 1000000 * *counter, error_ms * 1000000);
    std::this_thread::sleep_for(std::chrono::milliseconds(task_length_ms));
  }

  RepeatingAlarm* alarm_;

  common::Closure should_not_happen_ = common::Bind([] { ASSERT_TRUE(false); });

 private:
  Thread* thread_;
  Handler* handler_;
};

TEST_F(RepeatingAlarmTest, cancel_while_not_armed) {
  alarm_->Cancel();
}

TEST_F(RepeatingAlarmTest, schedule) {
  std::promise<void> promise;
  auto future = promise.get_future();
  auto before = std::chrono::steady_clock::now();
  int period_ms = 10;
  alarm_->Schedule(
      common::Bind(&std::promise<void>::set_value, common::Unretained(&promise)), std::chrono::milliseconds(period_ms));
  future.get();
  alarm_->Cancel();
  auto after = std::chrono::steady_clock::now();
  auto duration = after - before;
  ASSERT_NEAR(duration.count(), period_ms * 1000000, error_ms * 1000000);
}

TEST_F(RepeatingAlarmTest, cancel_alarm) {
  alarm_->Schedule(should_not_happen_, std::chrono::milliseconds(10));
  alarm_->Cancel();
  std::this_thread::sleep_for(std::chrono::milliseconds(50));
}

TEST_F(RepeatingAlarmTest, cancel_alarm_from_callback) {
  alarm_->Schedule(
      common::Bind(&RepeatingAlarm::Cancel, common::Unretained(this->alarm_)), std::chrono::milliseconds(1));
  std::this_thread::sleep_for(std::chrono::milliseconds(5));
}

TEST_F(RepeatingAlarmTest, schedule_while_alarm_armed) {
  alarm_->Schedule(should_not_happen_, std::chrono::milliseconds(1));
  std::promise<void> promise;
  auto future = promise.get_future();
  alarm_->Schedule(
      common::Bind(&std::promise<void>::set_value, common::Unretained(&promise)), std::chrono::milliseconds(10));
  future.get();
  alarm_->Cancel();
}

TEST_F(RepeatingAlarmTest, delete_while_alarm_armed) {
  alarm_->Schedule(should_not_happen_, std::chrono::milliseconds(1));
  delete alarm_;
  alarm_ = nullptr;
  std::this_thread::sleep_for(std::chrono::milliseconds(1));
}

TEST_F(RepeatingAlarmTest, verify_small) {
  VerifyMultipleDelayedTasks(100, 1, 10);
}

TEST_F(RepeatingAlarmTest, verify_large) {
  VerifyMultipleDelayedTasks(100, 3, 10);
}

}  // namespace
}  // namespace os
}  // namespace bluetooth
