// 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_log_sink/log_sink.h"

#include <atomic>
#include <cstring>
#include <mutex>

#include "pw_log/levels.h"
#include "pw_log/proto/log.pwpb.h"
#include "pw_protobuf/wire_format.h"
#include "pw_status/try.h"
#include "pw_string/string_builder.h"
#include "pw_sync/interrupt_spin_lock.h"

namespace pw::log_sink {
namespace {
// TODO: Make buffer sizes configurable.
constexpr size_t kMaxMessageStringSize = 32;
constexpr size_t kEncodeBufferSize = 128;

size_t drop_count = 0;

// The sink list and its corresponding lock are Meyer's singletons, to ensure
// they are constructed before use. This enables us to use logging before C++
// global construction has completed.
IntrusiveList<Sink>& sink_list() {
  static IntrusiveList<Sink> sink_list;
  return sink_list;
}

pw::sync::InterruptSpinLock& sink_list_lock() {
  // TODO(pwbug/304): Make lock selection configurable, some applications may
  // not be able to tolerate interrupt jitter and may prefer a pw::sync::Mutex.
  static pw::sync::InterruptSpinLock sink_list_lock;
  return sink_list_lock;
}

}  // namespace

// This is a fully loaded, inefficient-at-the-callsite, log implementation.
extern "C" void pw_LogSink_Log(int level,
                               unsigned int flags,
                               const char* /* module_name */,
                               const char* /* file_name */,
                               int line_number,
                               const char* /* function_name */,
                               const char* message,
                               ...) {
  // Encode message to the LogEntry protobuf.
  std::byte encode_buffer[kEncodeBufferSize];
  pw::protobuf::NestedEncoder nested_encoder(encode_buffer);
  pw::log::LogEntry::Encoder encoder(&nested_encoder);

  encoder.WriteLineLevel(
      (level & PW_LOG_LEVEL_BITMASK) |
      ((line_number << PW_LOG_LEVEL_BITS) & ~PW_LOG_LEVEL_BITMASK));
  encoder.WriteFlags(flags);

  // TODO(pwbug/301): Insert reasonable values for thread and timestamp.
  encoder.WriteTimestamp(0);

  // Accumulate the log message in this buffer, then output it.
  pw::StringBuffer<kMaxMessageStringSize> buffer;
  va_list args;

  va_start(args, message);
  buffer.FormatVaList(message, args);
  va_end(args);
  encoder.WriteMessage(std::as_bytes(std::span(buffer.view())));

  ConstByteSpan log_entry;
  Status status = nested_encoder.Encode(&log_entry);
  bool is_entry_valid = buffer.status().ok() && status.ok();

  // TODO(pwbug/305): Consider using a shared buffer between users. For now,
  // only lock after completing the encoding.
  {
    const std::lock_guard<pw::sync::InterruptSpinLock> lock(sink_list_lock());

    // If no sinks are configured, ignore the message. When sinks are attached,
    // they will receive this drop count to indicate logs drop to early boot.
    // The drop count is cleared after it is sent to a sink, so sinks attached
    // later will not receive drop counts from early boot.
    if (sink_list().size() == 0) {
      drop_count++;
      return;
    }

    // If an encoding failure occurs or the constructed log entry is larger
    // than the maximum allowed size, the log is dropped.
    if (!is_entry_valid) {
      drop_count++;
    }

    // Push entries to all attached sinks. This is a synchronous operation, so
    // attached sinks should avoid blocking when processing entries. If the log
    // entry is not valid, only the drop notification is sent to the sinks.
    for (auto& sink : sink_list()) {
      // The drop count is always provided before sending entries, to ensure the
      // sink processes drops in-order.
      if (drop_count > 0) {
        sink.HandleDropped(drop_count);
      }
      if (is_entry_valid) {
        sink.HandleEntry(log_entry);
      }
    }
    // All sinks have been notified of any drops.
    drop_count = 0;
  }
}

void AddSink(Sink& sink) {
  const std::lock_guard lock(sink_list_lock());
  sink_list().push_back(sink);
}

void RemoveSink(Sink& sink) {
  const std::lock_guard lock(sink_list_lock());
  sink_list().remove(sink);
}

}  // namespace pw::log_sink
