// 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 "common/strings/patch.h"

#include <algorithm>
#include <deque>
#include <functional>
#include <iostream>
#include <iterator>
#include <string>
#include <vector>

#include "absl/base/macros.h"
#include "absl/status/status.h"
#include "absl/strings/ascii.h"
#include "absl/strings/match.h"
#include "absl/strings/numbers.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/str_split.h"
#include "common/strings/position.h"
#include "common/strings/split.h"
#include "common/util/algorithm.h"
#include "common/util/container_iterator_range.h"
#include "common/util/file_util.h"
#include "common/util/iterator_adaptors.h"
#include "common/util/iterator_range.h"
#include "common/util/status_macros.h"
#include "common/util/user_interaction.h"

namespace verible {

static bool LineMarksOldFile(absl::string_view line) {
  return absl::StartsWith(line, "--- ");
}

static bool IsValidMarkedLine(absl::string_view line) {
  if (line.empty()) return false;
  switch (line.front()) {
    case ' ':
    case '-':
    case '+':
      return true;
    default:
      return false;
  }
}

namespace internal {

template <typename RangeT, typename Iter>
static std::vector<RangeT> IteratorsToRanges(const std::vector<Iter> &iters) {
  // TODO(fangism): This pattern appears elsewhere in the codebase, so refactor.
  CHECK_GE(iters.size(), 2);
  std::vector<RangeT> result;
  result.reserve(iters.size());
  auto prev = iters.begin();
  for (auto next = std::next(prev); next != iters.end(); prev = next, ++next) {
    result.emplace_back(*prev, *next);
  }
  return result;
}

absl::Status MarkedLine::Parse(absl::string_view text) {
  // text is already a whole line
  if (!IsValidMarkedLine(text)) {
    return absl::InvalidArgumentError(absl::StrCat(
        "MarkedLine must begin with one of [ -+], but got: \"", text, "\"."));
  }
  line.assign(text.begin(), text.end());  // copy
  return absl::OkStatus();
}

std::ostream &operator<<(std::ostream &stream, const MarkedLine &line) {
  const term::Color c = line.IsDeleted() ? term::Color::kRed
                        : line.IsAdded() ? term::Color::kCyan
                                         : term::Color::kNone;
  return term::Colored(stream, line.line, c);
}

std::string HunkIndices::FormatToString() const {
  return absl::StrCat(start, ",", count);
}

absl::Status HunkIndices::Parse(absl::string_view text) {
  // text is expected to look like "int,int"
  StringSpliterator splitter(text);
  const absl::string_view start_text = splitter(',');
  const absl::string_view count_text = splitter(',');
  if (!absl::SimpleAtoi(start_text, &start) ||  //
      !absl::SimpleAtoi(count_text, &count) ||  //
      splitter /* unexpected second ',' */) {
    return absl::InvalidArgumentError(
        absl::StrCat("HunkIndices expects int,int, but got: ", text, "\"."));
  }
  return absl::OkStatus();
}

std::ostream &operator<<(std::ostream &stream, const HunkIndices &indices) {
  return stream << indices.FormatToString();
}

absl::Status HunkHeader::Parse(absl::string_view text) {
  constexpr absl::string_view kDelimiter("@@");
  StringSpliterator tokenizer(text);
  {
    absl::string_view first = tokenizer(kDelimiter);
    // first token should be empty
    if (!first.empty() || !tokenizer) {
      return absl::InvalidArgumentError(absl::StrCat(
          "HunkHeader should start with @@, but got: ", text, "\"."));
    }
  }

  // Parse ranges between the "@@"s.
  {
    const absl::string_view ranges =
        absl::StripAsciiWhitespace(tokenizer(kDelimiter));
    if (!tokenizer) {
      return absl::InvalidArgumentError(absl::StrCat(
          "HunkHeader expects ranges in @@...@@, but got: ", text, "\"."));
    }

    auto splitter = MakeStringSpliterator(ranges, ' ');
    absl::string_view old_range_str(splitter());
    if (!absl::ConsumePrefix(&old_range_str, "-")) {
      return absl::InvalidArgumentError(absl::StrCat(
          "old-file range should start with '-', but got: ", old_range_str,
          "\"."));
    }
    absl::string_view new_range_str(splitter());
    if (!absl::ConsumePrefix(&new_range_str, "+")) {
      return absl::InvalidArgumentError(absl::StrCat(
          "new-file range should start with '+', but got: ", new_range_str,
          "\"."));
    }
    RETURN_IF_ERROR(old_range.Parse(old_range_str));
    RETURN_IF_ERROR(new_range.Parse(new_range_str));
  }

  // Text that follows the last "@@" provides context and is optional.
  const absl::string_view trailing_text = tokenizer(kDelimiter);
  context.assign(trailing_text.begin(), trailing_text.end());

  return absl::OkStatus();
}

std::ostream &operator<<(std::ostream &stream, const HunkHeader &header) {
  return term::Colored(
      stream,
      absl::StrCat("@@ -", header.old_range.FormatToString(), " +",
                   header.new_range.FormatToString(), " @@", header.context),
      term::Color::kGreen);
}

// Type M could be any container or range of MarkedLines.
template <class M>
static void CountMarkedLines(const M &lines, int *before, int *after) {
  *before = 0;
  *after = 0;
  for (const MarkedLine &line : lines) {
    switch (line.Marker()) {
      case ' ':  // line is common to both, unchanged
        ++*before;
        ++*after;
        break;
      case '-':
        ++*before;
        break;
      case '+':
        ++*after;
        break;
    }
  }
}

absl::Status Hunk::IsValid() const {
  int original_lines = 0;
  int new_lines = 0;
  CountMarkedLines(lines_, &original_lines, &new_lines);
  if (original_lines != header_.old_range.count) {
    return absl::InvalidArgumentError(
        absl::StrCat("Hunk is invalid: expected ", header_.old_range.count,
                     " lines before, but got ", original_lines, "."));
  }
  if (new_lines != header_.new_range.count) {
    return absl::InvalidArgumentError(
        absl::StrCat("Hunk is invalid: expected ", header_.new_range.count,
                     " lines after, but got ", new_lines, "."));
  }
  return absl::OkStatus();
}

void Hunk::UpdateHeader() {
  CountMarkedLines(lines_, &header_.old_range.count, &header_.new_range.count);
}

LineNumberSet Hunk::AddedLines() const {
  LineNumberSet line_numbers;
  int line_number = header_.new_range.start;
  for (const MarkedLine &line : lines_) {
    if (line.IsAdded()) line_numbers.Add(line_number);
    if (!line.IsDeleted()) ++line_number;
  }

  return line_numbers;
}

absl::Status Hunk::VerifyAgainstOriginalLines(
    const std::vector<absl::string_view> &original_lines) const {
  int line_number = header_.old_range.start;  // 1-indexed
  for (const MarkedLine &line : lines_) {
    if (line.IsAdded()) continue;  // ignore added lines
    if (line_number > static_cast<int>(original_lines.size())) {
      return absl::OutOfRangeError(absl::StrCat(
          "Patch hunk references line ", line_number, " in a file with only ",
          original_lines.size(), " lines"));
    }
    const absl::string_view original_line = original_lines[line_number - 1];
    if (line.Text() != original_line) {
      return absl::DataLossError(absl::StrCat(
          "Patch is inconsistent with original file!\nHunk at line ",
          line_number, " expected:\n", line.Text(), "\nbut got (original):\n",
          original_line, "\n"));
    }
    ++line_number;
  }
  return absl::OkStatus();
}

class HunkSplitter {
 public:
  HunkSplitter() = default;

  bool operator()(const MarkedLine &line) {
    if (previous_line_ == nullptr) {
      // first line
      previous_line_ = &line;
      return true;
    }
    const bool new_hunk = !previous_line_->IsCommon() && line.IsCommon();
    previous_line_ = &line;
    return new_hunk;
  }

 private:
  const MarkedLine *previous_line_ = nullptr;
};

std::vector<Hunk> Hunk::Split() const {
  std::vector<Hunk> sub_hunks;

  // Split after every group of changed lines.
  using MarkedLineIterator = std::vector<MarkedLine>::const_iterator;
  std::vector<MarkedLineIterator> cut_points;
  verible::find_all(lines_.begin(), lines_.end(),
                    std::back_inserter(cut_points), HunkSplitter());
  CHECK(!cut_points.empty());

  // Check whether or not there any line changes after the last cut point.
  // If not, then delete that cut point, which merges the last two partitions.
  if (cut_points.back() != lines_.begin()) {
    const bool last_partition_has_any_changes =
        std::any_of(cut_points.back(), lines_.end(),
                    [](const MarkedLine &m) { return !m.IsCommon(); });
    if (!last_partition_has_any_changes) cut_points.pop_back();
  }
  cut_points.push_back(lines_.end());  // always terminate partitions with end()
  // cut_points always contains lines_.begin(), and .end()

  // convert cut points to sub-ranges
  using MarkedLineRange = container_iterator_range<MarkedLineIterator>;
  const std::vector<MarkedLineRange> ranges(
      IteratorsToRanges<MarkedLineRange>(cut_points));

  // create sub hunks from each sub-range
  int old_starting_line = header_.old_range.start;
  int new_starting_line = header_.new_range.start;
  for (const MarkedLineRange &marked_line_range : ranges) {
    sub_hunks.emplace_back(old_starting_line, new_starting_line,
                           marked_line_range.begin(), marked_line_range.end());
    const HunkHeader &recent_header(sub_hunks.back().Header());
    old_starting_line += recent_header.old_range.count;
    new_starting_line += recent_header.new_range.count;
  }
  // TODO(b/161416776): if the resulting sub_hunks is singleton, then attempt to
  // further subdivide line-by-line.
  return sub_hunks;
}

absl::Status Hunk::Parse(const LineRange &hunk_lines) {
  RETURN_IF_ERROR(header_.Parse(hunk_lines.front()));

  LineRange body(hunk_lines);
  body.pop_front();  // remove the header
  lines_.resize(body.size());
  auto line_iter = lines_.begin();
  for (const auto &line : body) {
    RETURN_IF_ERROR(line_iter->Parse(line));
    ++line_iter;
  }
  return IsValid();
}

std::ostream &Hunk::Print(std::ostream &stream) const {
  stream << header_ << std::endl;
  for (const MarkedLine &line : lines_) {
    stream << line << std::endl;
  }
  return stream;
}

std::ostream &operator<<(std::ostream &stream, const Hunk &hunk) {
  return hunk.Print(stream);
}

absl::Status SourceInfo::Parse(absl::string_view text) {
  StringSpliterator splitter(text);

  absl::string_view token = splitter('\t');
  path.assign(token.begin(), token.end());
  if (path.empty()) {
    return absl::InvalidArgumentError(absl::StrCat(
        R"(Expected "path [timestamp]" (tab-separated), but got: ")", text,
        "\"."));
  }

  // timestamp is optional, allowed to be empty
  token = splitter('\t');  // time string (optional) is not parsed any further
  timestamp.assign(token.begin(), token.end());

  return absl::OkStatus();
}

std::ostream &operator<<(std::ostream &stream, const SourceInfo &info) {
  stream << info.path;
  if (!info.timestamp.empty()) stream << '\t' << info.timestamp;
  return stream;
}

static absl::Status ParseSourceInfoWithMarker(
    SourceInfo *info, absl::string_view line,
    absl::string_view expected_marker) {
  StringSpliterator splitter(line);
  absl::string_view marker = splitter(' ');
  if (marker != expected_marker) {
    return absl::InvalidArgumentError(
        absl::StrCat("Expected old-file marker \"", expected_marker,
                     "\", but got: \"", marker, "\""));
  }
  return info->Parse(splitter.Remainder());
}

bool FilePatch::IsNewFile() const { return old_file_.path == "/dev/null"; }

bool FilePatch::IsDeletedFile() const { return new_file_.path == "/dev/null"; }

LineNumberSet FilePatch::AddedLines() const {
  LineNumberSet line_numbers;
  for (const Hunk &hunk : hunks_) {
    line_numbers.Union(hunk.AddedLines());
  }
  return line_numbers;
}

static char PromptHunkAction(std::istream &ins, std::ostream &outs) {
  // Suppress prompt in noninteractive mode.
  term::bold(outs, "Apply this hunk? [y,n,a,d,s,q,?] ");
  char c;
  ins >> c;  // user will need to hit <enter> after the character
  if (ins.eof()) {
    outs << "Reached end of user input, abandoning changes to this file and "
            "all remaining files."
         << std::endl;
    return 'q';
  }
  return c;
}

absl::Status FilePatch::VerifyAgainstOriginalLines(
    const std::vector<absl::string_view> &original_lines) const {
  for (const Hunk &hunk : hunks_) {
    RETURN_IF_ERROR(hunk.VerifyAgainstOriginalLines(original_lines));
  }
  return absl::OkStatus();
}

absl::Status FilePatch::PickApplyInPlace(std::istream &ins,
                                         std::ostream &outs) const {
  return PickApply(ins, outs, &file::GetContentAsString, &file::SetContents);
}

absl::Status FilePatch::PickApply(std::istream &ins, std::ostream &outs,
                                  const FileReaderFunction &file_reader,
                                  const FileWriterFunction &file_writer) const {
  if (IsDeletedFile()) return absl::OkStatus();  // ignore
  if (IsNewFile()) return absl::OkStatus();      // ignore

  // Since this structure represents a patch, we need to retrieve the original
  // file's contents in whole.
  // If we had control over diff/patch generation, then we could rely on the
  // original diff structure/stream to provide original contents.
  // Below, we VerifyAgainstOriginalLines for all hunks in this FilePatch.
  const absl::StatusOr<std::string> orig_file_or = file_reader(old_file_.path);
  if (!orig_file_or.ok()) return orig_file_or.status();

  if (!hunks_.empty()) {
    // Display the file being processed, if there are any hunks.
    term::Colored(outs, absl::StrCat("--- ", old_file_.path, "\n"),
                  term::Color::kRed);
    term::Colored(outs, absl::StrCat("+++ ", new_file_.path, "\n"),
                  term::Color::kCyan);
  }

  const std::vector<absl::string_view> orig_lines(SplitLines(*orig_file_or));
  RETURN_IF_ERROR(VerifyAgainstOriginalLines(orig_lines));

  // Accumulate lines to write here.
  // Needs own copy of string due to potential splitting into temporary hunks.
  std::vector<std::string> output_lines;

  int last_consumed_line = 0;                                     // 0-indexed
  std::deque<Hunk> hunks_worklist(hunks_.begin(), hunks_.end());  // copy-fill
  while (!hunks_worklist.empty()) {
    VLOG(1) << "hunks remaining: " << hunks_worklist.size();
    const Hunk &hunk(hunks_worklist.front());

    // Copy over unchanged lines before this hunk.
    const auto &old_range = hunk.Header().old_range;
    if (old_range.start < last_consumed_line) {
      return absl::InvalidArgumentError(
          absl::StrCat("Hunks are not properly ordered.  last_consumed_line=",
                       last_consumed_line, ", but current hunk starts at line ",
                       old_range.start));
    }
    for (; last_consumed_line < old_range.start - 1; ++last_consumed_line) {
      CHECK_LT(last_consumed_line, static_cast<int>(orig_lines.size()));
      const absl::string_view &line(orig_lines[last_consumed_line]);
      output_lines.emplace_back(line.begin(), line.end());  // copy string
    }
    VLOG(1) << "copied up to (!including) line[" << last_consumed_line << "].";

    // Prompt user to apply or reject patch hunk.
    std::function<char()> prompt = [&hunk, &ins, &outs]() -> char {
      outs << hunk;
      return PromptHunkAction(ins, outs);
    };
    const char action = prompt();
    VLOG(1) << "user entered: " << action;
    switch (action) {
      case 'a': {
        // accept all remaining hunks in the current file
        prompt = []() -> char { return 'y'; };  // suppress prompt
        ABSL_FALLTHROUGH_INTENDED;
      }
      case 'y': {
        // accept this hunk, copy lines over
        for (const MarkedLine &marked_line : hunk.MarkedLines()) {
          if (!marked_line.IsDeleted()) {
            const absl::string_view line(marked_line.Text());
            output_lines.emplace_back(line.begin(), line.end());  // copy string
          }
        }
        last_consumed_line = old_range.start + old_range.count - 1;
        break;  // switch
      }
      case 'd': {
        // reject all remaining hunks in the current file
        prompt = []() -> char { return 'n'; };  // suppress prompt
        ABSL_FALLTHROUGH_INTENDED;
      }
      case 'n':
        // reject this hunk
        // no need to do anything, next iteration will sweep up original lines
        break;  // switch
      case 's': {
        // split this hunk into smaller ones and prompt again
        const auto sub_hunks = hunk.Split();
        hunks_worklist.pop_front();  // replace current hunk with sub-hunks
        // maintain sequential order of sub-hunks in the queue by line number
        for (const auto &sub_hunk : verible::reversed_view(sub_hunks)) {
          hunks_worklist.push_front(sub_hunk);
        }
        continue;  // for-loop
      }
      // TODO(b/156530527): 'e' for hunk editing
      case 'q':
        // Abort this file, discard any elected edits.
        outs << "Leaving file " << old_file_.path << " unchanged." << std::endl;
        return absl::OkStatus();
      default:  // including '?'
        outs << "y - accept change\n"
                "n - reject change\n"
                "a - accept this and remaining changes in the current file\n"
                "d - reject this and remaining changes in the current file\n"
                "s - split this hunk into smaller ones and prompt each one\n"
                "q - abandon all changes in this file\n"
                "? - print this help and prompt again\n";
        continue;  // for-loop
    }

    hunks_worklist.pop_front();
  }
  // Copy over remaining lines after the last hunk.
  for (; last_consumed_line < static_cast<int>(orig_lines.size());
       ++last_consumed_line) {
    const absl::string_view &line(orig_lines[last_consumed_line]);
    output_lines.emplace_back(line.begin(), line.end());  // copy string
  }
  VLOG(1) << "copied reamining lines up to [" << last_consumed_line << "].";

  const std::string rewrite_contents(absl::StrJoin(output_lines, "\n") + "\n");

  return file_writer(old_file_.path, rewrite_contents);
}

absl::Status FilePatch::Parse(const LineRange &lines) {
  LineIterator line_iter(
      std::find_if(lines.begin(), lines.end(), &LineMarksOldFile));
  if (lines.begin() == lines.end() || line_iter == lines.end()) {
    return absl::InvalidArgumentError(
        "Expected a file marker starting with \"---\", but did not find one.");
  }
  // Lines leading up to the old file marker "---" are metadata.
  for (const auto &line : make_range(lines.begin(), line_iter)) {
    metadata_.emplace_back(line);
  }

  RETURN_IF_ERROR(ParseSourceInfoWithMarker(&old_file_, *line_iter, "---"));
  ++line_iter;
  if (line_iter == lines.end()) {
    return absl::InvalidArgumentError(
        "Expected a file marker starting with \"+++\", but did not find one.");
  }
  RETURN_IF_ERROR(ParseSourceInfoWithMarker(&new_file_, *line_iter, "+++"));

  ++line_iter;

  // find hunk starts, and parse ranges of hunk texts
  std::vector<LineIterator> hunk_starts;
  find_all(
      line_iter, lines.end(), std::back_inserter(hunk_starts),
      [](absl::string_view line) { return absl::StartsWith(line, "@@ "); });

  if (hunk_starts.empty()) {
    // Unusual, but degenerate case of no hunks is parseable and valid.
    return absl::OkStatus();
  }

  hunk_starts.push_back(lines.end());  // make it easier to construct ranges
  const std::vector<LineRange> hunk_ranges(
      IteratorsToRanges<LineRange>(hunk_starts));

  hunks_.resize(hunk_ranges.size());
  auto hunk_iter = hunks_.begin();
  for (const auto &hunk_range : hunk_ranges) {
    RETURN_IF_ERROR(hunk_iter->Parse(hunk_range));
    ++hunk_iter;
  }
  return absl::OkStatus();
}

std::ostream &FilePatch::Print(std::ostream &stream) const {
  for (const std::string &line : metadata_) {
    stream << line << std::endl;
  }
  stream << "--- " << old_file_ << '\n'  //
         << "+++ " << new_file_ << std::endl;
  for (const Hunk &hunk : hunks_) {
    stream << hunk;
  }
  return stream;
}

std::ostream &operator<<(std::ostream &stream, const FilePatch &patch) {
  return patch.Print(stream);
}

}  // namespace internal

static bool LineBelongsToPreviousSection(absl::string_view line) {
  if (line.empty()) return true;
  return IsValidMarkedLine(line);
}

absl::Status PatchSet::Parse(absl::string_view patch_contents) {
  // Split lines.  The resulting lines will not include the \n delimiters.
  std::vector<absl::string_view> lines(
      absl::StrSplit(patch_contents, absl::ByChar('\n')));

  // Consider an empty patch file valid.
  if (lines.empty()) return absl::OkStatus();

  // Well-formed files end with a newline [POSIX], so delete the last partition.
  internal::LineRange lines_range(lines.cbegin(), std::prev(lines.cend()));

  // Split set of lines into ranges that correspond to individual files.
  // Strategy: find all old-file lines that start with "--- ", and then
  // search backwards to find the last line that starts with one of [ +-].
  std::vector<internal::LineIterator> file_patch_begins;
  {
    find_all(lines_range.begin(), lines_range.end(),
             std::back_inserter(file_patch_begins), &LineMarksOldFile);
    if (file_patch_begins.empty()) return absl::OkStatus();

    // Move line iterators back to correct starting points.
    for (auto &iter : file_patch_begins) {
      while (iter != lines_range.begin()) {
        const auto prev = std::prev(iter);
        const absl::string_view &peek(*prev);
        if (LineBelongsToPreviousSection(peek)) break;
        iter = prev;
      }
    }

    // For easier construction of ranges, append an end() iterator.
    file_patch_begins.push_back(lines_range.end());
  }

  // Record metadata lines, if there are any.
  for (const auto &line :
       make_range(lines_range.begin(), file_patch_begins.front())) {
    metadata_.emplace_back(line);
  }

  // Parse individual file patches.
  const std::vector<internal::LineRange> file_patch_ranges(
      internal::IteratorsToRanges<internal::LineRange>(file_patch_begins));
  file_patches_.resize(file_patch_ranges.size());
  auto iter = file_patches_.begin();
  for (const auto &range : file_patch_ranges) {
    RETURN_IF_ERROR(iter->Parse(range));
    ++iter;
  }

  // TODO(fangism): pass around line numbers to include in diagnostics

  return absl::OkStatus();
}

std::ostream &PatchSet::Render(std::ostream &stream) const {
  for (const auto &line : metadata_) {
    stream << line << std::endl;
  }
  for (const internal::FilePatch &file_patch : file_patches_) {
    stream << file_patch;
  }
  return stream;
}

FileLineNumbersMap PatchSet::AddedLinesMap(bool new_file_ranges) const {
  FileLineNumbersMap result;
  for (const internal::FilePatch &file_patch : file_patches_) {
    if (file_patch.IsDeletedFile()) continue;
    LineNumberSet &entry = result[file_patch.NewFileInfo().path];
    if (file_patch.IsNewFile() && !new_file_ranges) {
      entry.clear();
    } else {
      entry = file_patch.AddedLines();
    }
  }
  return result;
}

absl::Status PatchSet::PickApplyInPlace(std::istream &ins,
                                        std::ostream &outs) const {
  return PickApply(ins, outs, &file::GetContentAsString, &file::SetContents);
}

absl::Status PatchSet::PickApply(
    std::istream &ins, std::ostream &outs,
    const internal::FileReaderFunction &file_reader,
    const internal::FileWriterFunction &file_writer) const {
  for (const internal::FilePatch &file_patch : file_patches_) {
    RETURN_IF_ERROR(file_patch.PickApply(ins, outs, file_reader, file_writer));
  }
  return absl::OkStatus();
}

std::ostream &operator<<(std::ostream &stream, const PatchSet &patch) {
  return patch.Render(stream);
}

}  // namespace verible
