// 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 "tools/gn/standard_out.h"

#include <stddef.h>

#include <vector>

#include "base/command_line.h"
#include "base/logging.h"
#include "base/strings/string_piece.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
#include "build/build_config.h"
#include "tools/gn/switches.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;

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
}

}  // namespace

#if defined(OS_WIN)

void OutputString(const std::string& output, TextDecoration dec) {
  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;
    }
  }

  std::string tmpstr = 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, "--", "\\--");
  }
  ::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 OutputString(const std::string& output, TextDecoration dec) {
  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\e[1m");
        break;
    }
  }

  std::string tmpstr = 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, "--", "\\--");
  }
  WriteToStdOut(tmpstr.data());

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

#endif

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

  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) {
  EnsureInitialized();

  bool first_header = true;
  bool in_body = false;
  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] != ' ') {
      if (is_markdown) {
        // GN's block-level formatting is converted to markdown as follows:
        // * The first heading is treated as an H2.
        // * Subsequent heading are treated as H3s.
        // * 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) {
          OutputString("## ", DECORATION_NONE);
          first_header = false;
        } 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) + "\n");
      continue;
    } else if (is_markdown && !line.empty() && !in_body) {
      OutputString("```\n", DECORATION_NONE);
      in_body = true;
    }

    // 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```\n");
}

