// Copyright 2018 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 <cstdio>
#include <cstdlib>
#include <cstring>
#include <thread>

#include <src/lib/fxl/command_line.h>
#include <src/lib/fxl/log_settings.h>
#include <src/lib/fxl/log_settings_command_line.h>
#include <src/lib/fxl/strings/string_number_conversions.h>
#include <lib/zx/channel.h>
#include <lib/zx/event.h>
#include <lib/zx/eventpair.h>
#include <lib/zx/port.h>
#include <zircon/process.h>
#include <zircon/processargs.h>
#include <zircon/syscalls.h>
#include <zircon/syscalls/port.h>

#include "garnet/lib/debugger_utils/breakpoints.h"
#include "garnet/lib/debugger_utils/util.h"

#include "test_helper.h"

using debugger_utils::ZxErrorString;

static void ExceptionHandlerThreadFunc(
    zx_handle_t thread, zx::port* eport, zx::event* event) {
  zx_koid_t tid = debugger_utils::GetKoid(thread);
  zx_status_t status = zx_task_bind_exception_port(
      thread, eport->get(), tid, 0);
  FXL_CHECK(status == ZX_OK) << "status: " << ZxErrorString(status);

  // Now that we've bound to the thread, notify the test.
  status = event->signal(0, ZX_EVENT_SIGNALED);
  FXL_CHECK(status == ZX_OK) << "status: " << ZxErrorString(status);

  for (;;) {
    zx_port_packet_t packet;
    zx_status_t status = eport->wait(zx::time::infinite(), &packet);
    FXL_CHECK(status == ZX_OK) << "status: " << ZxErrorString(status);

    if (packet.type == ZX_PKT_TYPE_USER) {
      // Sent to trigger loop exit.
      break;
    }

    FXL_CHECK(ZX_PKT_IS_EXCEPTION(packet.type));
    FXL_CHECK(packet.type == ZX_EXCP_SW_BREAKPOINT);
    FXL_CHECK(packet.key == tid);
    status = debugger_utils::ResumeAfterSoftwareBreakpointInstruction(
        thread, eport->get());
    FXL_CHECK(status == ZX_OK);
  }
}

static void SendSelfThread(const zx::channel& channel) {
  // Send the parent a packet so that it knows we've started.
  zx_handle_t self_copy;
  zx_status_t status = zx_handle_duplicate(
      zx_thread_self(), ZX_RIGHT_SAME_RIGHTS, &self_copy);
  FXL_CHECK(status == ZX_OK) << "status: " << ZxErrorString(status);
  status = channel.write(0, nullptr, 0, &self_copy, 1);
  FXL_CHECK(status == ZX_OK) << "status: " << ZxErrorString(status);
}

static void WaitPeerClosed(const zx::channel& channel) {
  zx_status_t status = channel.wait_one(ZX_CHANNEL_PEER_CLOSED,
                                        zx::time::infinite(), nullptr);
  FXL_CHECK(status == ZX_OK) << "status: " << ZxErrorString(status);
}

static int PerformWaitPeerClosed(const zx::channel& channel) {
  SendSelfThread(channel);
  WaitPeerClosed(channel);
  printf("wait-peer-closed complete\n");
  return 0;
}

static int TriggerSoftwareBreakpoint(const zx::channel& channel,
                                     bool with_handler) {
  zx::port eport;
  zx_status_t status = zx::port::create(0, &eport);
  FXL_CHECK(status == ZX_OK) << "status: " << ZxErrorString(status);

  if (with_handler) {
    zx::event event;
    status = zx::event::create(0, &event);
    FXL_CHECK(status == ZX_OK) << "status: " << ZxErrorString(status);

    zx_handle_t self_thread = zx_thread_self();
    std::thread exception_thread(
      &ExceptionHandlerThreadFunc, self_thread, &eport, &event);

    // Don't trigger the s/w breakpoint until the exception loop is ready
    // to handle it.
    status = event.wait_one(ZX_EVENT_SIGNALED, zx::time::infinite(), nullptr);
    FXL_CHECK(status == ZX_OK) << "status: " << ZxErrorString(status);

    debugger_utils::TriggerSoftwareBreakpoint();

    WaitPeerClosed(channel);

    // Tell the exception thread to exit.
    zx_port_packet_t packet{};
    status = eport.queue(&packet);
    FXL_CHECK(status == ZX_OK) << "status: " << ZxErrorString(status);
    exception_thread.join();

    printf("trigger-sw-bkpt-with-handler complete\n");
  } else {
    debugger_utils::TriggerSoftwareBreakpoint();

    WaitPeerClosed(channel);

    printf("trigger-sw-bkpt complete\n");
  }

  return 0;
}

void WaitChannelReadable(const zx::channel& channel) {
  zx_signals_t pending;
  FXL_CHECK(channel.wait_one(ZX_CHANNEL_READABLE, zx::time::infinite(),
                             &pending) == ZX_OK);
}

static void ReadUint64Packet(const zx::channel& channel,
                             uint64_t expected_value) {
  uint64_t packet;
  uint32_t packet_size;
  FXL_CHECK(channel.rea2(0, &packet, nullptr, sizeof(packet), 0,
                         &packet_size,  nullptr) == ZX_OK);
  FXL_CHECK(packet_size == sizeof(packet));
  FXL_CHECK(packet == expected_value);
}

static void StartNThreadsThreadFunc(zx_handle_t eventpair) {
  // The main thread will close its side of |eventpair| when it's done.
  zx_signals_t pending;
  zx_status_t status = zx_object_wait_one(eventpair, ZX_EVENTPAIR_PEER_CLOSED,
                                          ZX_TIME_INFINITE, &pending);
  FXL_CHECK(status == ZX_OK);
}

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

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

  // What we want to do here is start a new thread and then wait for the
  // test to do its thing, and repeat.

  for (int i = 0; i < num_iterations; ++i) {
    FXL_VLOG(1) << "StartNThreads iteration " << i + 1;

    threads.emplace_back(
        std::thread{StartNThreadsThreadFunc, their_event.get()});

    WaitChannelReadable(channel);
    ReadUint64Packet(channel, inferior_control::kUint64MagicPacketValue);
  }

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

  return 0;
}

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

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

  if (!args.empty()) {
    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()) {
      FXL_LOG(WARNING) << "No handle provided";
    }

    const std::string& cmd = args[0];
    if (cmd == "wait-peer-closed") {
      return PerformWaitPeerClosed(channel);
    }
    if (cmd == "trigger-sw-bkpt") {
      return TriggerSoftwareBreakpoint(channel, false);
    }
    if (cmd == "trigger-sw-bkpt-with-handler") {
      return TriggerSoftwareBreakpoint(channel, true);
    }
    if (cmd == "start-n-threads") {
      if (args.size() < 2) {
        FXL_LOG(ERROR) << "Missing iteration count";
        return 1;
      }
      int num_threads = 0;
      if (!fxl::StringToNumberWithError(args[1], &num_threads) ||
          num_threads < 1) {
        FXL_LOG(ERROR) << "Error parsing number of threads";
        return 1;
      }
      return StartNThreads(channel, num_threads);
    }
    FXL_LOG(ERROR) << "Unrecognized command: " << cmd;
    return 1;
  }

  printf("Hello.\n");
  return 0;
}
