// Copyright 2017-2020 The Verible 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
//
//      http://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 <functional>
#include <iostream>
#include <string>
#include <utility>

#include "absl/flags/usage.h"
#include "absl/status/status.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/string_view.h"
#include "common/strings/patch.h"
#include "common/util/file_util.h"
#include "common/util/init_command_line.h"
#include "common/util/status_macros.h"
#include "common/util/subcommand.h"
#include "common/util/user_interaction.h"

using verible::SubcommandArgsRange;
using verible::SubcommandEntry;

static absl::Status ChangedLines(const SubcommandArgsRange &args,
                                 std::istream &ins, std::ostream &outs,
                                 std::ostream &errs) {
  if (args.empty()) {
    return absl::InvalidArgumentError(
        "Missing patchfile argument.  Use '-' for stdin.");
  }
  const absl::string_view patchfile = args[0];
  auto patch_content_or = verible::file::GetContentAsString(patchfile);
  if (!patch_content_or.ok()) return patch_content_or.status();

  verible::PatchSet patch_set;
  RETURN_IF_ERROR(patch_set.Parse(*patch_content_or));

  const verible::FileLineNumbersMap changed_lines(
      patch_set.AddedLinesMap(false));
  for (const auto &file_lines : changed_lines) {
    outs << file_lines.first;
    if (!file_lines.second.empty()) {
      file_lines.second.FormatInclusive(outs << ' ', true);
    }
    outs << std::endl;
  }
  return absl::OkStatus();
}

static absl::Status ApplyPick(const SubcommandArgsRange &args,
                              std::istream &ins, std::ostream &outs,
                              std::ostream &errs) {
  if (args.empty()) {
    return absl::InvalidArgumentError("Missing patchfile argument.");
  }
  const absl::string_view patchfile = args[0];
  absl::StatusOr<std::string> patch_contents_or;
  patch_contents_or = verible::file::GetContentAsString(patchfile);
  if (!patch_contents_or.ok()) return patch_contents_or.status();

  verible::PatchSet patch_set;
  RETURN_IF_ERROR(patch_set.Parse(*patch_contents_or));

  return patch_set.PickApplyInPlace(ins, outs);
}

static absl::Status StdinTest(const SubcommandArgsRange &args,
                              std::istream &ins, std::ostream &outs,
                              std::ostream &errs) {
  constexpr size_t kOpenLimit = 10;
  outs << "This is a demo of re-opening std::cin, up to " << kOpenLimit
       << " times.\n"
          "Enter text when prompted.\n"
          "Ctrl-D sends an EOF to start the next file.\n"
          "Ctrl-C terminates the loop and exits the program."
       << std::endl;
  size_t file_count = 0;
  std::string line;
  for (; file_count < kOpenLimit; ++file_count) {
    outs << "==== file " << file_count << " ====" << std::endl;
    while (ins) {
      if (verible::IsInteractiveTerminalSession(outs)) outs << "enter text: ";
      std::getline(ins, line);
      outs << "echo: " << line << std::endl;
    }
    if (ins.eof()) {
      outs << "EOF reached.  Re-opening for next file" << std::endl;
      ins.clear();  // allows std::cin to read the next file
    }
  }
  return absl::OkStatus();
}

static absl::Status CatTest(const SubcommandArgsRange &args, std::istream &ins,
                            std::ostream &outs, std::ostream &errs) {
  size_t file_count = 0;
  for (const auto &arg : args) {
    const absl::StatusOr<std::string> contents_or =
        verible::file::GetContentAsString(arg);
    if (!contents_or.ok()) return contents_or.status();

    outs << "<<<< contents of file[" << file_count << "] (" << arg << ") <<<<"
         << std::endl;
    outs << *contents_or;
    outs << ">>>> end of file[" << file_count << "] (" << arg << ") >>>>"
         << std::endl;
    ++file_count;
  }
  return absl::OkStatus();
}

static const std::pair<absl::string_view, SubcommandEntry> kCommands[] = {
    {"changed-lines",  //
     {&ChangedLines,   //
      R"(changed-lines patchfile

Input:
'patchfile' is a unified-diff file from 'diff -u' or other version-controlled
equivalents like {p4,git,hg,cvs,svn} diff.  Use '-' to read from stdin.

Output: (stdout)
This prints output in the following format per line:

  filename [line-ranges]

where line-ranges (optional) is suitable for tools that accept a set of lines
to operate on, e.g. "1-4,8,21-42".
line-ranges is omitted for files that are considered new in the patchfile.
)"}},

    // TODO(b/156530527): add options like -p for path pruning
    // TODO(fangism): Support '-' as patchfile.
    {"apply-pick",
     {&ApplyPick,
      R"(apply-pick patchfile
Input:
'patchfile' is a unified-diff file from 'diff -u' or other version-controlled
equivalents like {p4,git,hg,cvs,svn} diff.

Effect:
Modifies patched files in-place, following user selections on which patch
hunks to apply.
)"}},

    {"stdin-test",  //
     {&StdinTest,   //
      R"(Test for re-opening stdin.

This interactivel prompts the user to enter text, separating files with an EOF
(Ctrl-D), and echoes the input text back to stdout.
)",
      false}},
    {"cat-test",  //
     {&CatTest,   //
      R"(Test for (UNIX) cat-like functionality.

Usage: cat-test ARGS...

where each ARG could point to a file on the filesystem or be '-' to read from stdin.
Each '-' will prompt the user to enter text until EOF (Ctrl-D).
Each 'file' echoed back to stdout will be enclosed in banner lines with
<<<< and >>>>.
)",
      false}},
};

int main(int argc, char *argv[]) {
  // Create a registry of subcommands (locally, rather than as a static global).
  verible::SubcommandRegistry commands;
  for (const auto &entry : kCommands) {
    const auto status = commands.RegisterCommand(entry.first, entry.second);
    if (!status.ok()) {
      std::cerr << status.message() << std::endl;
      return 2;  // fatal error
    }
  }

  const std::string usage = absl::StrCat("usage: ", argv[0],
                                         " command args...\n"
                                         "available commands:\n",
                                         commands.ListCommands());

  // Process invocation args.
  const auto args = verible::InitCommandLine(usage, &argc, &argv);
  if (args.size() == 1) {
    std::cerr << absl::ProgramUsageMessage() << std::endl;
    return 1;
  }
  // args[0] is the program name
  // args[1] is the subcommand
  // subcommand args start at [2]
  const SubcommandArgsRange command_args(args.cbegin() + 2, args.cend());

  const auto &sub = commands.GetSubcommandEntry(args[1]);
  // Run the subcommand.
  const auto status = sub.main(command_args, std::cin, std::cout, std::cerr);
  if (!status.ok()) {
    std::cerr << status.message() << std::endl;
    return 1;
  }
  return 0;
}
