// Copyright (c) 2013 The Chromium 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 "gn/standard_out.h"

#include <stddef.h>

#include <mutex>
#include <string_view>
#include <vector>

#include "base/command_line.h"
#include "base/logging.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
#include "gn/switches.h"
#include "util/build_config.h"

#if defined(OS_WIN)
#include <windows.h>
#else
#include <stdio.h>
#include <unistd.h>
#endif

namespace {

bool initialized = false;

#if defined(OS_WIN)
HANDLE hstdout;
WORD default_attributes;
#endif
bool is_console = false;

bool is_markdown = false;

// True while output is going into a markdown ```...``` code block.
bool in_body = false;

void EnsureInitialized() {
  if (initialized)
    return;
  initialized = true;

  const base::CommandLine* cmdline = base::CommandLine::ForCurrentProcess();
  if (cmdline->HasSwitch(switches::kMarkdown)) {
    // Output help in Markdown's syntax, not color-highlighted.
    is_markdown = true;
  }

  if (cmdline->HasSwitch(switches::kNoColor)) {
    // Force color off.
    is_console = false;
    return;
  }

#if defined(OS_WIN)
  // On Windows, we can't force the color on. If the output handle isn't a
  // console, there's nothing we can do about it.
  hstdout = ::GetStdHandle(STD_OUTPUT_HANDLE);
  CONSOLE_SCREEN_BUFFER_INFO info;
  is_console = !!::GetConsoleScreenBufferInfo(hstdout, &info);
  default_attributes = info.wAttributes;
#else
  if (cmdline->HasSwitch(switches::kColor))
    is_console = true;
  else
    is_console = isatty(fileno(stdout));
#endif
}

#if !defined(OS_WIN)
void WriteToStdOut(const std::string& output) {
  size_t written_bytes = fwrite(output.data(), 1, output.size(), stdout);
  DCHECK_EQ(output.size(), written_bytes);
}
#endif  // !defined(OS_WIN)

void OutputMarkdownDec(TextDecoration dec) {
  // The markdown rendering turns "dim" text to italics and any
  // other colored text to bold.

#if defined(OS_WIN)
  DWORD written = 0;
  if (dec == DECORATION_DIM)
    ::WriteFile(hstdout, "*", 1, &written, nullptr);
  else if (dec != DECORATION_NONE)
    ::WriteFile(hstdout, "**", 2, &written, nullptr);
#else
  if (dec == DECORATION_DIM)
    WriteToStdOut("*");
  else if (dec != DECORATION_NONE)
    WriteToStdOut("**");
#endif
}

#if defined(OS_WIN)

void WriteOutputString(std::string_view output,
                       TextDecoration dec,
                       HtmlEscaping escaping) {
  EnsureInitialized();
  DWORD written = 0;

  if (is_markdown) {
    OutputMarkdownDec(dec);
  } else if (is_console) {
    switch (dec) {
      case DECORATION_NONE:
        break;
      case DECORATION_DIM:
        ::SetConsoleTextAttribute(hstdout, FOREGROUND_INTENSITY);
        break;
      case DECORATION_RED:
        ::SetConsoleTextAttribute(hstdout,
                                  FOREGROUND_RED | FOREGROUND_INTENSITY);
        break;
      case DECORATION_GREEN:
        // Keep green non-bold.
        ::SetConsoleTextAttribute(hstdout, FOREGROUND_GREEN);
        break;
      case DECORATION_BLUE:
        ::SetConsoleTextAttribute(hstdout,
                                  FOREGROUND_BLUE | FOREGROUND_INTENSITY);
        break;
      case DECORATION_YELLOW:
        ::SetConsoleTextAttribute(hstdout, FOREGROUND_RED | FOREGROUND_GREEN);
        break;
      case DECORATION_MAGENTA:
        ::SetConsoleTextAttribute(
            hstdout, FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY);
        break;
    }
  }

  std::string tmpstr = std::string(output);
  if (is_markdown && dec == DECORATION_YELLOW) {
    // https://code.google.com/p/gitiles/issues/detail?id=77
    // Gitiles will replace "--" with an em dash in non-code text.
    // Figuring out all instances of this might be difficult, but we can
    // at least escape the instances where this shows up in a heading.
    base::ReplaceSubstringsAfterOffset(&tmpstr, 0, "--", "\\--");
  }
  if (is_markdown && !in_body && escaping == DEFAULT_ESCAPING) {
    // Markdown auto-escapes < and > in code sections (and converts &lt; to
    // &amp;tl; there), but not elsewhere.
    base::ReplaceSubstringsAfterOffset(&tmpstr, 0, "<", "&lt;");
    base::ReplaceSubstringsAfterOffset(&tmpstr, 0, ">", "&gt;");
  }
  ::WriteFile(hstdout, tmpstr.c_str(), static_cast<DWORD>(tmpstr.size()),
              &written, nullptr);

  if (is_markdown) {
    OutputMarkdownDec(dec);
  } else if (is_console) {
    ::SetConsoleTextAttribute(hstdout, default_attributes);
  }
}

#else

void WriteOutputString(std::string_view output,
                       TextDecoration dec,
                       HtmlEscaping escaping) {
  EnsureInitialized();
  if (is_markdown) {
    OutputMarkdownDec(dec);
  } else if (is_console) {
    switch (dec) {
      case DECORATION_NONE:
        break;
      case DECORATION_DIM:
        WriteToStdOut("\e[2m");
        break;
      case DECORATION_RED:
        WriteToStdOut("\e[31m\e[1m");
        break;
      case DECORATION_GREEN:
        WriteToStdOut("\e[32m");
        break;
      case DECORATION_BLUE:
        WriteToStdOut("\e[34m\e[1m");
        break;
      case DECORATION_YELLOW:
        WriteToStdOut("\e[33m");
        break;
      case DECORATION_MAGENTA:
        WriteToStdOut("\e[35m\e[1m");
        break;
    }
  }

  std::string tmpstr = std::string(output);
  if (is_markdown && dec == DECORATION_YELLOW) {
    // https://code.google.com/p/gitiles/issues/detail?id=77
    // Gitiles will replace "--" with an em dash in non-code text.
    // Figuring out all instances of this might be difficult, but we can
    // at least escape the instances where this shows up in a heading.
    base::ReplaceSubstringsAfterOffset(&tmpstr, 0, "--", "\\--");
  }
  if (is_markdown && !in_body && escaping == DEFAULT_ESCAPING) {
    // Markdown auto-escapes < and > in code sections (and converts &lt; to
    // &amp;tl; there), but not elsewhere.
    base::ReplaceSubstringsAfterOffset(&tmpstr, 0, "<", "&lt;");
    base::ReplaceSubstringsAfterOffset(&tmpstr, 0, ">", "&gt;");
  }
  WriteToStdOut(tmpstr.data());

  if (is_markdown) {
    OutputMarkdownDec(dec);
  } else if (is_console && dec != DECORATION_NONE) {
    WriteToStdOut("\e[0m");
  }
}

#endif

// Collects buffered log output for quiet mode.
class QuietModeBuffer {
 public:
  using BufferedOutput = ScopedBufferedOutput::Item;

  void Append(std::string_view output,
              TextDecoration decoration,
              HtmlEscaping escaping) {
    {
      std::lock_guard<std::mutex> lock(lock_);
      if (!is_flushed_) {
        output_buffer_.push_back({std::string(output), decoration, escaping});
        return;
      }
      // Otherwise fall-through to printing to stdout outside the lock.
    }
    WriteOutputString(output, decoration, escaping);
  }

  // Outputs any queued output to the standard out.
  void Flush() {
    // Do everything inside the lock so we guarantee we flush all previous
    // output before writing something else from another thread. Flushing will
    // only happen in error cases so this will not be performance-critical.
    std::lock_guard<std::mutex> lock(lock_);

    if (is_flushed_)
      return;
    is_flushed_ = true;

    for (const BufferedOutput& output : output_buffer_) {
      WriteOutputString(output.output, output.decoration, output.escaping);
    }
    output_buffer_.clear();
  }

  // Take a snapshot of the current buffers output items.
  std::vector<BufferedOutput> GetItems() {
    std::lock_guard<std::mutex> lock(lock_);
    return output_buffer_;
  }

 private:
  std::mutex lock_;

  // Set when we're in quiet mode but then flush the output. This means that
  // future output should go directly to the terminal (this solves the problem
  // of safely turning "off" quiet mode when we hit an error because
  // quiet_mode_buffer isn't threadsafe).
  bool is_flushed_ = false;

  std::vector<BufferedOutput> output_buffer_;
};

// Non-null while buffering standard output. Deliberately leaked on shutdown.
QuietModeBuffer* quiet_mode_buffer = nullptr;

// Non-null while ScopedBufferedOutput singleton exists.
QuietModeBuffer* scoped_output_buffer = nullptr;

}  // namespace

bool IsColorEnabled() {
  EnsureInitialized();
  return is_console;
}

void OutputString(std::string_view output,
                  TextDecoration dec,
                  HtmlEscaping escaping) {
  if (scoped_output_buffer) {
    scoped_output_buffer->Append(output, dec, escaping);
    return;
  }
  WriteOutputString(output, dec, escaping);
}

void OutputLogString(std::string_view output,
                     TextDecoration dec,
                     HtmlEscaping escaping) {
  if (scoped_output_buffer) {
    scoped_output_buffer->Append(output, dec, escaping);
    return;
  }
  if (quiet_mode_buffer) {
    quiet_mode_buffer->Append(output, dec, escaping);
    return;
  }
  WriteOutputString(output, dec, escaping);
}

void BufferLogOutput() {
  if (quiet_mode_buffer) {
    DCHECK(false);  // Expecting to only be called once.
    return;
  }
  quiet_mode_buffer = new QuietModeBuffer();
}

void FlushBufferedLogOutput() {
  if (quiet_mode_buffer) {
    quiet_mode_buffer->Flush();
  }
}

ScopedBufferedOutput::ScopedBufferedOutput() {
  DCHECK(!scoped_output_buffer)
      << "Only one ScopedBufferedOutput instance can exist";
  scoped_output_buffer = new QuietModeBuffer();
}

ScopedBufferedOutput::~ScopedBufferedOutput() {
  DCHECK(scoped_output_buffer);
  delete scoped_output_buffer;
  scoped_output_buffer = nullptr;
}

std::vector<ScopedBufferedOutput::Item> ScopedBufferedOutput::GetItems() {
  DCHECK(scoped_output_buffer);
  return scoped_output_buffer->GetItems();
}

void PrintSectionHelp(const std::string& line,
                      const std::string& topic,
                      const std::string& tag) {
  EnsureInitialized();

  if (is_markdown) {
    OutputString("*   [" + line + "](#" + tag + ")\n");
  } else if (topic.size()) {
    OutputString("\n" + line + " (type \"gn help " + topic +
                 "\" for more help):\n");
  } else {
    OutputString("\n" + line + ":\n");
  }
}

void PrintShortHelp(const std::string& line, const std::string& link_tag) {
  EnsureInitialized();

  if (is_markdown) {
    if (link_tag.empty())
      OutputString("    *   " + line + "\n");
    else
      OutputString("    *   [" + line + "](#" + link_tag + ")\n");
    return;
  }

  size_t colon_offset = line.find(':');
  size_t first_normal = 0;
  if (colon_offset != std::string::npos) {
    OutputString("  " + line.substr(0, colon_offset), DECORATION_YELLOW);
    first_normal = colon_offset;
  }

  // See if the colon is followed by a " [" and if so, dim the contents of [ ].
  if (first_normal > 0 && line.size() > first_normal + 2 &&
      line[first_normal + 1] == ' ' && line[first_normal + 2] == '[') {
    size_t begin_bracket = first_normal + 2;
    OutputString(": ");
    first_normal = line.find(']', begin_bracket);
    if (first_normal == std::string::npos)
      first_normal = line.size();
    else
      first_normal++;
    OutputString(line.substr(begin_bracket, first_normal - begin_bracket),
                 DECORATION_DIM);
  }

  OutputString(line.substr(first_normal) + "\n");
}

void PrintLongHelp(const std::string& text, const std::string& tag) {
  EnsureInitialized();

  bool first_header = true;
  in_body = false;
  std::size_t empty_lines = 0;
  for (const std::string& line : base::SplitString(
           text, "\n", base::KEEP_WHITESPACE, base::SPLIT_WANT_ALL)) {
    // Check for a heading line.
    if (!line.empty() && line[0] != ' ') {
      // New paragraph, just skip any trailing empty lines.
      empty_lines = 0;

      if (is_markdown) {
        // GN's block-level formatting is converted to markdown as follows:
        // * The first heading is treated as an H3.
        // * Subsequent heading are treated as H4s.
        // * Any other text is wrapped in a code block and displayed as-is.
        //
        // Span-level formatting (the decorations) is converted inside
        // OutputString().
        if (in_body) {
          OutputString("```\n\n", DECORATION_NONE);
          in_body = false;
        }

        if (first_header && !tag.empty()) {
          OutputString("### <a name=\"" + tag + "\"></a>", DECORATION_NONE,
                       NO_ESCAPING);
        } else {
          OutputString("#### ", DECORATION_NONE);
        }
      }

      // Highlight up to the colon (if any).
      size_t chars_to_highlight = line.find(':');
      if (chars_to_highlight == std::string::npos)
        chars_to_highlight = line.size();

      OutputString(line.substr(0, chars_to_highlight), DECORATION_YELLOW);
      OutputString(line.substr(chars_to_highlight));
      if (first_header) {
        if (is_markdown) {
          OutputString("&nbsp;[Back to Top](#gn-reference)", DECORATION_NONE);
        }
        first_header = false;
      }
      OutputString("\n");
      continue;
    } else if (is_markdown && !line.empty() && !in_body) {
      OutputString("```\n", DECORATION_NONE);
      in_body = true;
    }

    // We buffer empty lines, so we can skip them if needed
    // (i.e. new paragraph body, end of final paragraph body).
    if (in_body && is_markdown) {
      if (!line.empty() && empty_lines != 0) {
        OutputString(std::string(empty_lines, '\n'));
        empty_lines = 0;
      } else if (line.empty()) {
        ++empty_lines;
        continue;
      }
    }

    // Check for a comment.
    TextDecoration dec = DECORATION_NONE;
    for (const auto& elem : line) {
      if (elem == '#' && !is_markdown) {
        // Got a comment, draw dimmed.
        dec = DECORATION_DIM;
        break;
      } else if (elem != ' ') {
        break;
      }
    }

    OutputString(line + "\n", dec);
  }

  if (is_markdown && in_body)
    OutputString("```\n");
}
