// Copyright 2017 The Fuchsia 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 <lib/fdio/io.h>
#include <lib/fit/defer.h>
#include <stdio.h>
#include <threads.h>
#include <unistd.h>
#include <zircon/errors.h>
#include <zircon/syscalls.h>
#include <zircon/time.h>
#include <zircon/types.h>

#include <algorithm>
#include <limits>
#include <utility>

#include <fbl/algorithm.h>
#include <fbl/alloc_checker.h>
#include <fbl/intrusive_single_list.h>

static constexpr uint32_t kDefaultNumThreads = 4;
static constexpr float kDefaultMinWorkMsec = 5.0f;
static constexpr float kDefaultMaxWorkMsec = 15.0f;
static constexpr float kDefaultMinSleepMsec = 1.0f;
static constexpr float kDefaultMaxSleepMsec = 2.5f;

class LoadGeneratorThread : public fbl::SinglyLinkedListable<std::unique_ptr<LoadGeneratorThread>> {
 public:
  LoadGeneratorThread(unsigned int seed) : seed_(seed) {}
  ~LoadGeneratorThread();

  zx_status_t Start();

  static float& min_work_msec() { return min_work_msec_; }
  static float& max_work_msec() { return max_work_msec_; }
  static float& min_sleep_msec() { return min_sleep_msec_; }
  static float& max_sleep_msec() { return max_sleep_msec_; }

 private:
  int Run();

  double MakeRandomDouble(double min, double max);

  static float min_work_msec_;
  static float max_work_msec_;
  static float min_sleep_msec_;
  static float max_sleep_msec_;
  static volatile bool quit_;

  unsigned int seed_;
  bool thread_started_;
  thrd_t thread_;
  volatile double accumulator_;
};

float LoadGeneratorThread::min_work_msec_ = kDefaultMinWorkMsec;
float LoadGeneratorThread::max_work_msec_ = kDefaultMaxWorkMsec;
float LoadGeneratorThread::min_sleep_msec_ = kDefaultMinSleepMsec;
float LoadGeneratorThread::max_sleep_msec_ = kDefaultMaxSleepMsec;
volatile bool LoadGeneratorThread::quit_ = false;

LoadGeneratorThread::~LoadGeneratorThread() {
  if (thread_started_) {
    int musl_ret;
    quit_ = true;
    thrd_join(thread_, &musl_ret);
  }
}

zx_status_t LoadGeneratorThread::Start() {
  if (thread_started_)
    return ZX_ERR_BAD_STATE;

  int c11_res = thrd_create(
      &thread_, [](void* ctx) -> int { return static_cast<LoadGeneratorThread*>(ctx)->Run(); },
      this);

  if (c11_res != thrd_success) {
    printf("Failed to create new client thread (res %d)!\n", c11_res);
    // TODO(johngro) : translate musl error
    return ZX_ERR_INTERNAL;
  }

  return ZX_OK;
}

int LoadGeneratorThread::Run() {
  constexpr double kMinNum = 1.0;
  constexpr double kMaxNum = 100000000.0;
  uint32_t ticks_per_msec = static_cast<uint32_t>(zx_ticks_per_second() / 1000);
  accumulator_ = MakeRandomDouble(kMinNum, kMaxNum);

  // While it is not time to quit, waste time performing pointless double
  // precision floating point math.
  while (!quit_) {
    double work_delay = MakeRandomDouble(min_work_msec(), max_work_msec());
    zx_ticks_t work_deadline_ticks =
        zx_ticks_get() + static_cast<zx_ticks_t>(work_delay * ticks_per_msec);

    while (!quit_ && (zx_ticks_get() < work_deadline_ticks)) {
      accumulator_ = accumulator_ + MakeRandomDouble(kMinNum, kMaxNum);
      accumulator_ = accumulator_ * MakeRandomDouble(kMinNum, kMaxNum);
      accumulator_ = accumulator_ - MakeRandomDouble(kMinNum, kMaxNum);
      accumulator_ = accumulator_ / MakeRandomDouble(kMinNum, kMaxNum);

      double tmp = accumulator_;
      accumulator_ = std::clamp<double>(tmp, 0.0, kMaxNum);
    }

    if (quit_)
      break;

    double sleep_delay = MakeRandomDouble(min_sleep_msec(), max_sleep_msec());
    zx_time_t sleep_deadline =
        zx_deadline_after(static_cast<zx_duration_t>(sleep_delay * 1000000.0));

    do {
      static constexpr zx_duration_t max_sleep = ZX_MSEC(10);
      zx_time_t now = zx_clock_get_monotonic();

      if (now >= sleep_deadline)
        break;

      if (zx_time_sub_time(sleep_deadline, now) > max_sleep) {
        zx_nanosleep(zx_time_add_duration(now, max_sleep));
      } else {
        zx_nanosleep(sleep_deadline);
        break;
      }
    } while (!quit_);
  }

  return 0;
}

double LoadGeneratorThread::MakeRandomDouble(double min, double max) {
  double norm(rand_r(&seed_));
  norm /= std::numeric_limits<int>::max();
  return min + (norm * (max - min));
}

void usage(const char* program_name) {
  printf(
      "usage: %s [N] [min_work max_work] [min_sleep max_sleep] [seed]\n"
      "  All arguments are positional and optional.\n"
      "  N             : Number of threads to create.  Default %u\n"
      "  min/max_work  : Min/max msec for threads to work for.  Default %.1f,%.1f mSec\n"
      "  min/max_sleep : Min/max msec for threads to sleep for.  Default %.1f,%.1f mSec\n"
      "  seed          : RNG seed to use.  Defaults to seeding from zx_clock_get\n",
      program_name, kDefaultNumThreads, kDefaultMinWorkMsec, kDefaultMaxWorkMsec,
      kDefaultMinSleepMsec, kDefaultMaxSleepMsec);
}

int main(int argc, char** argv) {
  auto show_usage = fit::defer([argv]() { usage(argv[0]); });

  // 0, 1, 3, 5 and 6 arguments are the only legal number of args.
  switch (argc) {
    case 1:
    case 2:
    case 4:
    case 6:
    case 7:
      break;
    default:
      return -1;
  }

  // Parse and sanity check number of threads, if present.
  uint32_t num_threads = kDefaultNumThreads;
  if (argc >= 2) {
    if (sscanf(argv[1], "%u", &num_threads) != 1)
      return -1;
    if (num_threads == 0)
      return -1;
  }

  // Parse and sanity check min/max work times, if present.
  if (argc >= 4) {
    if (sscanf(argv[2], "%f", &LoadGeneratorThread::min_work_msec()) != 1)
      return -1;
    if (sscanf(argv[3], "%f", &LoadGeneratorThread::max_work_msec()) != 1)
      return -1;
    if (LoadGeneratorThread::min_work_msec() <= 0.0f)
      return -1;
    if (LoadGeneratorThread::min_work_msec() > LoadGeneratorThread::max_work_msec())
      return -1;
  }

  // Parse and sanity check min/max sleep times, if present.
  if (argc >= 6) {
    if (sscanf(argv[4], "%f", &LoadGeneratorThread::min_sleep_msec()) != 1)
      return -1;
    if (sscanf(argv[5], "%f", &LoadGeneratorThread::max_sleep_msec()) != 1)
      return -1;
    if (LoadGeneratorThread::min_sleep_msec() <= 0.0f)
      return -1;
    if (LoadGeneratorThread::min_sleep_msec() > LoadGeneratorThread::max_sleep_msec())
      return -1;
  }

  // Parse the PRNG seed, if present.
  unsigned int seed = static_cast<unsigned int>(zx_clock_get_monotonic());
  if (argc >= 7) {
    if (sscanf(argv[6], "%u", &seed) != 1)
      return -1;
  }

  // Argument parsing checks out, cancel the showing of the usage message.
  show_usage.cancel();

  printf(
      "Creating %u load generation thread%s.\n"
      "Work times  : [%.3f, %.3f] mSec\n"
      "Sleep times : [%.3f, %.3f] mSec\n"
      "Seed        : %u\n",
      num_threads, num_threads == 1 ? "" : "s", LoadGeneratorThread::min_work_msec(),
      LoadGeneratorThread::max_work_msec(), LoadGeneratorThread::min_sleep_msec(),
      LoadGeneratorThread::max_sleep_msec(), seed);

  fbl::SinglyLinkedList<std::unique_ptr<LoadGeneratorThread>> threads;
  for (uint32_t i = 0; i < num_threads; ++i) {
    fbl::AllocChecker ac;
    std::unique_ptr<LoadGeneratorThread> t(new (&ac) LoadGeneratorThread(rand_r(&seed)));

    if (!ac.check()) {
      printf("Failed to create thread %u/%u\n", i + 1, num_threads);
      return -1;
    }

    threads.push_front(std::move(t));
  }

  for (auto& t : threads) {
    zx_status_t res = t.Start();
    if (res != ZX_OK) {
      printf("Failed to start thread.  (res %d)\n", res);
      return res;
    }
  }

  printf("Running.  Press any key to exit\n");

  uint32_t event = 0;
  bool state = false;
  printf("-");
  while (::fdio_wait_fd(STDIN_FILENO, FDIO_EVT_READABLE, &event, ZX_MSEC(500)) ==
         ZX_ERR_TIMED_OUT) {
    if ((state = !state)) {
      printf("\b-");
    } else {
      printf("\b|");
    }
  }

  printf("Shutting down...\n");
  threads.clear();
  printf("Finished\n");

  return 0;
}
