// 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.

#define PW_LOG_LEVEL PW_THREAD_EMBOS_CONFIG_LOG_LEVEL

#include "pw_thread_embos/snapshot.h"

#include <string_view>

#include "RTOS.h"
#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_embos/config.h"
#include "pw_thread_embos/util.h"
#include "pw_thread_protos/thread.pwpb.h"

namespace pw::thread::embos {
namespace {

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

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

  // One byte is reserved for task status.
  //   - The lowest two bits are for a suspend counter.
  //   - The third-lowest bit is reserved for a "timeout." (ignored here)
  //   - The highest five bits indicate what the task is blocked on if non-zero.
  //
  // Note: embOS thread state is not part of the public API. This may not be
  // correct for all versions. This has been tested on embOS 4.22, and was
  // initially reported for embOS 5.06.
  //
  // Description of how `OS_TASK::Stat` is used by embOS:
  //   https://forum.segger.com/index.php/Thread/6548-ABANDONED-Task-state-values/?postID=23963#post23963
#if OS_VERSION_GENERIC < 42200 || OS_VERSION_GENERIC > 50600
#warning embOS thread state interpretation logic is not verfied as working on this version of embOS
#endif  // OS_VERSION_GENERIC < 42200 || OS_VERSION_GENERIC > 50600

  if ((thread.Stat & 0x3) != 0) {
    PW_LOG_DEBUG("Thread state: SUSPENDED");
    encoder.WriteState(ThreadState::Enum::SUSPENDED);
  } else if ((thread.Stat & 0xf8) == 0) {
    PW_LOG_DEBUG("Thread state: READY");
    encoder.WriteState(ThreadState::Enum::READY);
  } else {
    PW_LOG_DEBUG("Thread state: BLOCKED");
    encoder.WriteState(ThreadState::Enum::BLOCKED);
  }
}

}  // 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 OS_TASK& 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() && !status.IsFailedPrecondition()) {
    PW_LOG_ERROR("Failed to iterate threads during snapshot capture: %d",
                 static_cast<int>(status.code()));
  }

  return ctx.thread_capture_status;
}

Status SnapshotThread(const OS_TASK& thread,
                      void* running_thread_stack_pointer,
                      Thread::StreamEncoder& encoder,
                      ProcessThreadStackCallback& thread_stack_callback) {
#if OS_TRACKNAME
  PW_LOG_DEBUG("Capturing thread info for %s", thread.Name);
  encoder.WriteName(as_bytes(span(std::string_view(thread.Name))));
#else
  PW_LOG_DEBUG("Capturing thread info for thread at 0x%08x", &thread);
#endif  // OS_TRACKNAME

  CaptureThreadState(thread, encoder);

#if OS_CHECKSTACK || OS_SUPPORT_MPU
  const StackContext thread_ctx = {
      .thread_name = thread.Name,

      .stack_low_addr = reinterpret_cast<uintptr_t>(thread.pStackBot),

      .stack_high_addr =
          reinterpret_cast<uintptr_t>(thread.pStackBot) + thread.StackSize,

      // 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.pStack),
      .stack_pointer_est_peak = reinterpret_cast<uintptr_t>(thread.pStackBot) +
                                thread.StackSize - OS_GetStackUsed(&thread),
  };

  return SnapshotStack(thread_ctx, encoder, thread_stack_callback);
#else
  PW_LOG_DEBUG("Stack pointer: 0x%08x", running_thread_stack_pointer);
  encoder.WriteStackPointer(reinterpret_cast<uintptr_t>(
      ThreadIsRunning(thread) ? running_thread_stack_pointer : thread.pStack));
  return encoder.status();
#endif  // OS_CHECKSTACK || OS_SUPPORT_MPU
}

}  // namespace pw::thread::embos
