// Copyright 2021 The Pigweed Authors
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not
// use this file except in compliance with the License. You may obtain a copy of
// the License at
//
//     https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations under
// the License.
#include "pw_thread_threadx/snapshot.h"

#include <string_view>

#include "pw_function/function.h"
#include "pw_log/log.h"
#include "pw_protobuf/encoder.h"
#include "pw_status/status.h"
#include "pw_thread/snapshot.h"
#include "pw_thread_protos/thread.pwpb.h"
#include "pw_thread_threadx/util.h"
#include "tx_api.h"
#include "tx_thread.h"

namespace pw::thread::threadx {
namespace {

// TODO(amontanez): This might make unit testing codepaths that use this more
// challenging.
inline bool ThreadIsRunning(const TX_THREAD& thread) {
  const TX_THREAD* running_thread;
  TX_THREAD_GET_CURRENT(running_thread);
  return running_thread == &thread;
}

void CaptureThreadState(const TX_THREAD& thread,
                        Thread::StreamEncoder& encoder) {
  if (ThreadIsRunning(thread)) {
    encoder.WriteState(ThreadState::Enum::RUNNING);
    return;
  }

  switch (thread.tx_thread_state) {
    case TX_READY:
      encoder.WriteState(ThreadState::Enum::READY);
      break;
    case TX_COMPLETED:
    case TX_TERMINATED:
      encoder.WriteState(ThreadState::Enum::INACTIVE);
      break;
    case TX_SUSPENDED:
    case TX_SLEEP:
      encoder.WriteState(ThreadState::Enum::SUSPENDED);
      break;
    case TX_QUEUE_SUSP:
    case TX_SEMAPHORE_SUSP:
    case TX_EVENT_FLAG:
    case TX_BLOCK_MEMORY:
    case TX_BYTE_MEMORY:
    case TX_IO_DRIVER:
    case TX_FILE:
    case TX_TCP_IP:
    case TX_MUTEX_SUSP:
      encoder.WriteState(ThreadState::Enum::BLOCKED);
      break;
    default:
      encoder.WriteState(ThreadState::Enum::UNKNOWN);
  }
}

}  // namespace

Status SnapshotThreads(void* running_thread_stack_pointer,
                       SnapshotThreadInfo::StreamEncoder& encoder,
                       ProcessThreadStackCallback& stack_dumper) {
  struct {
    void* running_thread_stack_pointer;
    SnapshotThreadInfo::StreamEncoder* encoder;
    ProcessThreadStackCallback* stack_dumper;
    Status thread_capture_status;
  } ctx;
  ctx.running_thread_stack_pointer = running_thread_stack_pointer;
  ctx.encoder = &encoder;
  ctx.stack_dumper = &stack_dumper;

  ThreadCallback thread_capture_cb([&ctx](const TX_THREAD& thread) -> bool {
    Thread::StreamEncoder thread_encoder = ctx.encoder->GetThreadsEncoder();
    ctx.thread_capture_status.Update(
        SnapshotThread(thread,
                       ctx.running_thread_stack_pointer,
                       thread_encoder,
                       *ctx.stack_dumper));
    // Always iterate all threads.
    return true;
  });

  if (Status status = ForEachThread(thread_capture_cb); !status.ok()) {
    PW_LOG_ERROR("Failed to iterate threads during snapshot capture: %d",
                 static_cast<int>(status.code()));
  }

  return ctx.thread_capture_status;
}

Status SnapshotThread(const TX_THREAD& thread,
                      void* running_thread_stack_pointer,
                      Thread::StreamEncoder& encoder,
                      ProcessThreadStackCallback& thread_stack_callback) {
  encoder.WriteName(
      std::as_bytes(std::span(std::string_view(thread.tx_thread_name))));

  CaptureThreadState(thread, encoder);

  const StackContext thread_ctx = {
      .thread_name = thread.tx_thread_name,

      // TODO(amontanez): When ThreadX is built with stack checking enabled, the
      // lowest-addressed `unsigned long` is reserved for a watermark. This
      // means in practice the stack pointer should never end up there. To be
      // conservative, behave as though TX_THREAD_STACK_CHECK is always fully
      // enabled.
      .stack_low_addr =
          reinterpret_cast<uintptr_t>(thread.tx_thread_stack_start) +
          sizeof(ULONG),

      .stack_high_addr =
          reinterpret_cast<uintptr_t>(thread.tx_thread_stack_end),

      // If the thread is active, the stack pointer in the TCB is stale.
      .stack_pointer = reinterpret_cast<uintptr_t>(
          ThreadIsRunning(thread) ? running_thread_stack_pointer
                                  : thread.tx_thread_stack_ptr),
  };

  return SnapshotStack(thread_ctx, encoder, thread_stack_callback);
}

}  // namespace pw::thread::threadx
