// Copyright 2019 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 "test_helper.h"

#include <lib/syslog/cpp/log_settings.h>
#include <lib/syslog/cpp/macros.h>
#include <lib/zx/channel.h>
#include <lib/zx/event.h>
#include <lib/zx/eventpair.h>
#include <stdio.h>
#include <stdlib.h>
#include <zircon/process.h>
#include <zircon/processargs.h>
#include <zircon/types.h>

#include <atomic>
#include <thread>

#include "src/lib/fxl/command_line.h"
#include "src/lib/fxl/log_settings_command_line.h"
#include "src/lib/fxl/strings/string_number_conversions.h"
#include "util.h"

std::atomic_int g_num_threads_running = 0;

static void WaitPeerClosed(const zx::channel& channel) {
  // Wait for the test to close the channel.
  zx_signals_t pending;
  zx_status_t status = channel.wait_one(ZX_CHANNEL_PEER_CLOSED, zx::time::infinite(), &pending);
  if (status != ZX_OK) {
    FX_LOGS(ERROR) << "Test helper: wait peer closed failed: "
                   << debugger_utils::ZxErrorString(status);
    exit(EXIT_FAILURE);
  }
}

static void WriteUint64Packet(const zx::channel& channel, uint64_t value) {
  uint64_t packet = value;
  FX_CHECK(channel.write(0, &packet, sizeof(packet), nullptr, 0) == ZX_OK);
}

static void StartNThreadsThreadFunc(zx_handle_t eventpair, int num_threads) {
  zx_status_t status;

  // When all threads are running notify the main loop.
  if (g_num_threads_running.fetch_add(1) == num_threads - 1) {
    FX_LOGS(INFO) << "All threads started";
    status = zx_object_signal_peer(eventpair, 0, ZX_USER_SIGNAL_0);
    FX_CHECK(status == ZX_OK);
  }

  // The main thread will close its side of |eventpair| when it's done.
  zx_signals_t pending;
  status = zx_object_wait_one(eventpair, ZX_EVENTPAIR_PEER_CLOSED, ZX_TIME_INFINITE, &pending);
  FX_CHECK(status == ZX_OK);
}

static int StartNThreads(zx::channel channel, int num_threads) {
  std::vector<std::thread> threads;

  // When our side of the event pair is closed the threads will exit.
  zx::eventpair our_event, their_event;
  FX_CHECK(zx::eventpair::create(0, &our_event, &their_event) == ZX_OK);

  for (int i = 0; i < num_threads; ++i) {
    threads.emplace_back(std::thread{StartNThreadsThreadFunc, their_event.get(), num_threads});
  }

  // Wait for all threads to start.
  zx_signals_t pending;
  zx_status_t status = our_event.wait_one(ZX_USER_SIGNAL_0, zx::time::infinite(), &pending);
  FX_CHECK(status == ZX_OK);

  // Notify test all threads are running.
  WriteUint64Packet(channel, debugger_utils::kUint64MagicPacketValue);

  WaitPeerClosed(channel);

  // Terminate the threads;
  our_event.reset();
  for (auto& thread : threads) {
    thread.join();
  }

  return EXIT_SUCCESS;
}

static int PerformWaitPeerClosed(zx::channel channel) {
  zx_handle_t thread = zx_thread_self();
  zx_status_t status = channel.write(0, nullptr, 0, &thread, 1);
  if (status != ZX_OK) {
    FX_LOGS(ERROR) << "Test helper: channel write failed: "
                   << debugger_utils::ZxErrorString(status);
    return EXIT_FAILURE;
  }

  WaitPeerClosed(channel);

  return EXIT_SUCCESS;
}

int main(int argc, char* argv[]) {
  auto cl = fxl::CommandLineFromArgcArgv(argc, argv);
  if (!fxl::SetLogSettingsFromCommandLine(cl)) {
    return EXIT_FAILURE;
  }

  const std::vector<std::string>& args = cl.positional_args();

  if (args.empty()) {
    FX_LOGS(ERROR) << "Missing command";
    return EXIT_FAILURE;
  }

  const std::string& cmd = args[0];
  FX_LOGS(INFO) << argv[0] << ": Command " << cmd;

  if (cmd == "hello") {
    FX_LOGS(INFO) << "Hello.";
    return EXIT_SUCCESS;
  }

  zx::channel channel{zx_take_startup_handle(PA_HND(PA_USER0, 0))};
  // If no channel was passed we're running standalone.
  if (!channel.is_valid()) {
    FX_LOGS(WARNING) << "Test helper: channel not received";
  }

  if (cmd == "wait-peer-closed") {
    return PerformWaitPeerClosed(std::move(channel));
  } else if (cmd == "start-n-threads") {
    if (args.size() < 2) {
      FX_LOGS(ERROR) << "Missing iteration count";
      return EXIT_FAILURE;
    }
    int num_threads = 0;
    if (!fxl::StringToNumberWithError(args[1], &num_threads) || num_threads < 1) {
      FX_LOGS(ERROR) << "Error parsing number of threads";
      return EXIT_FAILURE;
    }
    return StartNThreads(std::move(channel), num_threads);
  }

  FX_LOGS(ERROR) << "Unknown helper command";
  return EXIT_FAILURE;
}
