// Copyright (C) 2018  INRIA
//
// Treerecs is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// Treerecs is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program.  If not, see <https://www.gnu.org/licenses/>.

// Include Googletest
#include <gtest/gtest.h>

// Include Bpplib
#include <Bpp/Phyl/Tree/PhyloTree.h>

// Include containers
#include <memory>

// Include handlers, tools
#include <treerecs/tools/utils.h>
#include <treerecs/tools/Timer.h>

// Include examples paths
#include "examples_paths.h"

using namespace treerecs;

void sleep(int milliseconds);

void sleep(int milliseconds) // Cross-platform sleep function
{
  clock_t time_end;
  time_end = clock() + milliseconds * CLOCKS_PER_SEC/1000;
  while (clock() < time_end)
  {
  }
}

class Timer_tests: public testing::Test {
protected:
  virtual void SetUp() {
  };

  virtual void TearDown() {}
};

TEST_F(Timer_tests, timer_int_tests) {
  Timer<int> timer_int(10);
  ASSERT_EQ(0, timer_int.current());
  ASSERT_EQ(10, timer_int.max());
  ASSERT_EQ(0, timer_int.min());
  ASSERT_EQ(10, timer_int.total_number_of_steps());

  sleep(500);
  timer_int.next(5);
  ASSERT_EQ(5, timer_int.current());
  EXPECT_PRED_FORMAT2(::testing::DoubleLE, 0.5, timer_int.clocks_past());
  EXPECT_PRED_FORMAT2(::testing::DoubleLE, 0.5, timer_int.time_past());
  ASSERT_NEAR(0.1, timer_int.average_time_per_step(), 0.01);

  timer_int.next();
  ASSERT_EQ(6, timer_int.current());

  timer_int.setMaximum(5);
  ASSERT_EQ(5, timer_int.max());
}

TEST_F(Timer_tests, timer_double_tests) {
  Timer<double> timer_double(10);
  ASSERT_EQ(0, timer_double.current());
  ASSERT_EQ(10, timer_double.max());
  ASSERT_EQ(0, timer_double.min());
  ASSERT_EQ(10, timer_double.total_number_of_steps());

  sleep(500);
  timer_double.next(5);
  ASSERT_EQ(5.0, timer_double.current());
  EXPECT_PRED_FORMAT2(::testing::DoubleLE, 0.5, timer_double.clocks_past());
  EXPECT_PRED_FORMAT2(::testing::DoubleLE, 0.5, timer_double.time_past());
  ASSERT_NEAR(0.1, timer_double.average_time_per_step(), 0.01);

  timer_double.next(5.0);
  ASSERT_EQ(10, timer_double.current());

  timer_double.setMaximum(5.1);
  ASSERT_EQ(5.1, timer_double.max());

}