// 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 "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/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];
  std::string patch_contents;
  if (auto status = verible::file::GetContents(patchfile, &patch_contents);
      !status.ok()) {
    return status;
  }
  verible::PatchSet patch_set;
  if (auto status = patch_set.Parse(patch_contents); !status.ok()) {
    return status;
  }
  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];
  std::string patch_contents;
  if (auto status = verible::file::GetContents(patchfile, &patch_contents);
      !status.ok()) {
    return status;
  }
  verible::PatchSet patch_set;
  if (auto status = patch_set.Parse(patch_contents); !status.ok()) {
    return status;
  }
  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 << "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) {
    std::string contents;
    if (auto status = verible::file::GetContents(arg, &contents);
        !status.ok()) {
      return status;
    }
    outs << "<<<< contents of file[" << file_count << "] (" << arg << ") <<<<"
         << std::endl;
    outs << contents;
    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;
}
