// 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 <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 <lib/fdio/io.h>

#include <limits>
#include <utility>

#include <fbl/algorithm.h>
#include <fbl/alloc_checker.h>
#include <fbl/auto_call.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_ += MakeRandomDouble(kMinNum, kMaxNum);
      accumulator_ *= MakeRandomDouble(kMinNum, kMaxNum);
      accumulator_ -= MakeRandomDouble(kMinNum, kMaxNum);
      accumulator_ /= MakeRandomDouble(kMinNum, kMaxNum);

      double tmp = accumulator_;
      accumulator_ = fbl::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 = fbl::MakeAutoCall([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;
}
