// 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_{false};
  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;
}
