/*
 * Copyright (c) 2020-2023, NVIDIA CORPORATION. All rights reserved.
 *
 * This source code and/or documentation ("Licensed Deliverables") are
 * subject to NVIDIA intellectual property rights under U.S. and
 * international Copyright laws.
 */

#pragma once

#include <cugraph-ops/utils/cpu_timer.hpp>

#include <catch2/catch.hpp>

#include <algorithm>

namespace cugraph::ops::catch2 {

static char const* const K_DASHED_LINE =
  "--------------------------------------------------------------------------";

struct listener : Catch::TestEventListenerBase {
  using TestEventListenerBase::TestEventListenerBase;  // inherit ctor

  void testRunStarting(Catch::TestRunInfo const& info) override
  {
    cugraph::ops::utils::cpu::tic(info.name);
    std::cout << K_DASHED_LINE << std::endl
              << "Test started... [" << info.name << "] (all time in seconds)" << std::endl
              << K_DASHED_LINE << std::endl
              << std::flush;
  }

  void testRunEnded(Catch::TestRunStats const& stats) override
  {
    cugraph::ops::utils::cpu::toc(stats.runInfo.name);
    std::cout << K_DASHED_LINE << std::endl
              << "Time taken: " << cugraph::ops::utils::cpu::get_timer(stats.runInfo.name).elapsed()
              << std::endl
              << std::flush;
  }

  void testCaseStarting(Catch::TestCaseInfo const& info) override
  {
    static constexpr int TEST_NAME_LEN = 64;
    cugraph::ops::utils::cpu::tic(info.name);
    std::string name = info.name + " ... ";
    auto n_spaces    = TEST_NAME_LEN - std::min(TEST_NAME_LEN, static_cast<int>(name.size()));
    std::string spaces(n_spaces, ' ');
    std::cout << name << spaces << std::flush;
  }

  void testCaseEnded(Catch::TestCaseStats const& stats) override
  {
    const auto& name   = stats.testInfo.name;
    const char* status = stats.totals.assertions.allPassed() ? "OK" : "FAIL";
    cugraph::ops::utils::cpu::toc(name);
    std::cout << "[" << status << "] [" << cugraph::ops::utils::cpu::get_timer(name).elapsed()
              << "]" << std::endl
              << std::flush;
  }
};  // struct Listener

// there are various clang-tidy warnings here, since this listener has global
// state, uses anonymous namespace, etc. but all are intended by catch2
CATCH_REGISTER_LISTENER(listener);  // NOLINT

}  // namespace cugraph::ops::catch2
