/*
 * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 *
 */
#include "jvm.h"
#include "logging/logAsyncWriter.hpp"
#include "logging/logDecorations.hpp"
#include "logging/logDecorators.hpp"
#include "logging/logFileStreamOutput.hpp"
#include "logging/logMessageBuffer.hpp"
#include "memory/allocation.inline.hpp"
#include "utilities/defaultStream.hpp"
#include <string.h>

const char* const LogFileStreamOutput::FoldMultilinesOptionKey = "foldmultilines";

bool LogFileStreamOutput::set_option(const char* key, const char* value, outputStream* errstream) {
  bool success = false;
  if (strcmp(FoldMultilinesOptionKey, key) == 0) {
    if (strcmp(value, "true") == 0) {
      _fold_multilines = true;
      success = true;
    } else if (strcmp(value, "false") == 0) {
      _fold_multilines = false;
      success = true;
    } else {
      errstream->print_cr("Invalid option: %s must be 'true' or 'false'.", key);
    }
  }
  return success;
}

int LogFileStreamOutput::write_decorations(const LogDecorations& decorations) {
  int total_written = 0;
  char buf[LogDecorations::max_decoration_size + 1];

  for (uint i = 0; i < LogDecorators::Count; i++) {
    LogDecorators::Decorator decorator = static_cast<LogDecorators::Decorator>(i);
    if (!_decorators.is_decorator(decorator)) {
      continue;
    }

    int written = jio_fprintf(_stream, "[%-*s]",
                              _decorator_padding[decorator],
                              decorations.decoration(decorator, buf, sizeof(buf)));
    if (written <= 0) {
      return -1;
    } else if (static_cast<size_t>(written - 2) > _decorator_padding[decorator]) {
      _decorator_padding[decorator] = written - 2;
    }
    total_written += written;
  }
  return total_written;
}

class FileLocker : public StackObj {
private:
  FILE *_file;

public:
  FileLocker(FILE *file) : _file(file) {
    os::flockfile(_file);
  }

  ~FileLocker() {
    os::funlockfile(_file);
  }
};

bool LogFileStreamOutput::flush() {
  bool result = true;
  if (fflush(_stream) != 0) {
    if (!_write_error_is_shown) {
      jio_fprintf(defaultStream::error_stream(),
                  "Could not flush log: %s (%s (%d))\n", name(), os::strerror(errno), errno);
      jio_fprintf(_stream, "\nERROR: Could not flush log (%d)\n", errno);
      _write_error_is_shown = true;
    }
    result = false;
  }
  return result;
}

#define WRITE_LOG_WITH_RESULT_CHECK(op, total)                \
{                                                             \
  int result = op;                                            \
  if (result < 0) {                                           \
    if (!_write_error_is_shown) {                             \
      jio_fprintf(defaultStream::error_stream(),              \
                  "Could not write log: %s\n", name());       \
      jio_fprintf(_stream, "\nERROR: Could not write log\n"); \
      _write_error_is_shown = true;                           \
      return -1;                                              \
    }                                                         \
  }                                                           \
  total += result;                                            \
}

int LogFileStreamOutput::write_internal(const LogDecorations& decorations, const char* msg) {
  int written = 0;
  const bool use_decorations = !_decorators.is_empty();

  if (!_fold_multilines) {
    const char* base = msg;
    int decorator_padding = 0;
    if (use_decorations) {
      WRITE_LOG_WITH_RESULT_CHECK(write_decorations(decorations), decorator_padding);
      WRITE_LOG_WITH_RESULT_CHECK(jio_fprintf(_stream, " "), written);
    }
    written += decorator_padding;

    // Search for newlines in the string and repeatedly print the substrings that end
    // with each newline.
    const char* next = strstr(msg, "\n");
    while (next != nullptr) {  // We have some newlines to print
      int to_print = next - base;
      WRITE_LOG_WITH_RESULT_CHECK(jio_fprintf(_stream, "%.*s\n", to_print, base), written);
      if (use_decorations) {
        WRITE_LOG_WITH_RESULT_CHECK(jio_fprintf(_stream, "[%*c] ", decorator_padding - 2, ' '), written); // Substracting 2 because decorator_padding includes the brackets
      }
      base = next + 1;
      next = strstr(base, "\n");
    }

    // Print the end of the message
    WRITE_LOG_WITH_RESULT_CHECK(jio_fprintf(_stream, "%s\n", base), written);
  } else {
    if (use_decorations) {
      WRITE_LOG_WITH_RESULT_CHECK(write_decorations(decorations), written);
      WRITE_LOG_WITH_RESULT_CHECK(jio_fprintf(_stream, " "), written);
    }
    char *dupstr = os::strdup_check_oom(msg, mtLogging);
    char *cur = dupstr;
    char *next;
    do {
      next = strpbrk(cur, "\n\\");
      if (next == nullptr) {
        WRITE_LOG_WITH_RESULT_CHECK(jio_fprintf(_stream, "%s\n", cur), written);
      } else {
        const char *found = (*next == '\n') ? "\\n" : "\\\\";
        *next = '\0';
        WRITE_LOG_WITH_RESULT_CHECK(jio_fprintf(_stream, "%s%s", cur, found), written);
        cur = next + 1;
      }
    } while (next != nullptr);
    os::free(dupstr);
  }
  return written;
}

int LogFileStreamOutput::write_blocking(const LogDecorations& decorations, const char* msg) {
  FileLocker flocker(_stream);
  int written = write_internal(decorations, msg);
  return flush() ? written : -1;
}

int LogFileStreamOutput::write(const LogDecorations& decorations, const char* msg) {
  if (AsyncLogWriter::enqueue(*this, decorations, msg)) {
    return 0;
  }

  return write_blocking(decorations, msg);
}

int LogFileStreamOutput::write(LogMessageBuffer::Iterator msg_iterator) {
  if (AsyncLogWriter::enqueue(*this, msg_iterator)) {
    return 0;
  }

  int written = 0;
  FileLocker flocker(_stream);
  for (; !msg_iterator.is_at_end(); msg_iterator++) {
    written += write_internal(msg_iterator.decorations(), msg_iterator.message());
  }

  return flush() ? written : -1;
}

void LogFileStreamOutput::describe(outputStream *out) {
  LogOutput::describe(out);
  out->print(" ");

  out->print("foldmultilines=%s", _fold_multilines ? "true" : "false");
}
