// 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/diff.h"

#include <iostream>
#include <vector>

#include "absl/strings/str_split.h"
#include "common/strings/split.h"
#include "common/util/iterator_range.h"
#include "external_libs/editscript.h"

namespace verible {

using diff::Edit;
using diff::Edits;
using diff::Operation;

static char EditOperationToLineMarker(Operation op) {
  switch (op) {
    case Operation::DELETE:
      return '-';
    case Operation::EQUALS:
      return ' ';
    case Operation::INSERT:
      return '+';
    default:
      return '?';
  }
}

LineDiffs::LineDiffs(absl::string_view before, absl::string_view after)
    : before_text(before),
      after_text(after),
      before_lines(SplitLinesKeepLineTerminator(before_text)),
      after_lines(SplitLinesKeepLineTerminator(after_text)),
      edits(diff::GetTokenDiffs(before_lines.begin(), before_lines.end(),
                                after_lines.begin(), after_lines.end())) {}

template <typename Iter>
static std::ostream &PrintLineRange(std::ostream &stream, char op, Iter start,
                                    Iter end) {
  for (const auto &line : make_range(start, end)) {
    stream << op << line;
  }
  return stream;
}

std::ostream &LineDiffs::PrintEdit(std::ostream &stream,
                                   const Edit &edit) const {
  const char op = EditOperationToLineMarker(edit.operation);
  if (edit.operation == Operation::INSERT) {
    PrintLineRange(stream, op, after_lines.begin() + edit.start,
                   after_lines.begin() + edit.end);
    if (after_lines[edit.end - 1].back() != '\n') stream << "\n";
  } else {
    PrintLineRange(stream, op, before_lines.begin() + edit.start,
                   before_lines.begin() + edit.end);
    if (before_lines[edit.end - 1].back() != '\n') stream << "\n";
  }
  stream << std::flush;
  return stream;
}

std::ostream &operator<<(std::ostream &stream, const LineDiffs &diffs) {
  for (const auto &edit : diffs.edits) {
    diffs.PrintEdit(stream, edit);
  }
  return stream;
}

LineNumberSet DiffEditsToAddedLineNumbers(const Edits &edits) {
  LineNumberSet added_lines;
  for (const auto &edit : edits) {
    if (edit.operation == Operation::INSERT) {
      // Add 1 to convert from 0-indexed to 1-indexed.
      added_lines.Add(
          {static_cast<int>(edit.start) + 1, static_cast<int>(edit.end) + 1});
    }
  }
  return added_lines;
}

std::vector<diff::Edits> DiffEditsToPatchHunks(const diff::Edits &edits,
                                               int common_context) {
  const int split_threshold = common_context * 2;
  std::vector<diff::Edits> hunks(1);  // start with 1 empty destination vector
  for (const diff::Edit &edit : edits) {
    auto &current_hunk = hunks.back();
    if (edit.operation == Operation::EQUALS) {
      const int edit_size = edit.end - edit.start;
      if (current_hunk.empty()) {
        // For "end-pieces" (in this case, the head), threshold should be
        // common_context, not split_threshold.
        if (edit_size > common_context) {
          // Add the tail end of this edit.
          current_hunk.push_back(
              diff::Edit{edit.operation, edit.end - common_context, edit.end});
        } else {
          // Add the whole edit.
          current_hunk.push_back(edit);
        }
      } else {  // !current_hunk.empty()
        // We don't know what follows this edit, so this may still be oversized.
        // A final pass will trim excess sizing of EQUALS edits in tail
        // position.
        if (edit_size > split_threshold) {
          // Close off the current hunk.
          current_hunk.push_back(diff::Edit{edit.operation, edit.start,
                                            edit.start + common_context});
          // Start the next hunk.
          hunks.push_back(diff::Edits{
              diff::Edit{edit.operation, edit.end - common_context, edit.end}});
        } else {
          // Add the whole edit.
          current_hunk.push_back(edit);
        }
      }
    } else {  // operation is INSERT or DELETE
      current_hunk.push_back(edit);
    }
  }

  // The last hunk may have been started before knowing it was the last one.
  // Remove if it is a no-op.
  const auto &last_hunk = hunks.back();  // hunks is always non-empty
  if (last_hunk.size() == 1 &&
      last_hunk.front().operation == Operation::EQUALS) {
    // This last hunk's only element is an Operation::EQUALS (no-change),
    // so remove it.
    hunks.pop_back();
  }

  // Trim excess EQUALS tail edits in each hunk.
  for (auto &hunk : hunks) {
    auto &tail = hunk.back();
    if (tail.operation == Operation::EQUALS) {
      if (tail.end - tail.start > common_context) {
        tail.end = tail.start + common_context;
      }
    }
  }
  return hunks;
}

void LineDiffsToUnifiedDiff(std::ostream &stream, const LineDiffs &linediffs,
                            unsigned common_context, absl::string_view file_a,
                            absl::string_view file_b) {
  const std::vector<diff::Edits> chunks =
      DiffEditsToPatchHunks(linediffs.edits, common_context);

  if (chunks.empty()) return;

  if (!file_a.empty()) {
    if (file_b.empty()) {
      stream << "--- a/" << file_a << std::endl;
      stream << "+++ b/" << file_a << std::endl;
    } else {
      stream << "--- " << file_a << std::endl;
      stream << "+++ " << file_b << std::endl;
    }
  }

  int added_lines_count = 0;
  for (const auto &chunk : chunks) {
    int chunk_before_lines_count = 0;
    int chunk_added_lines_count = 0;

    for (const auto &edit : chunk) {
      if (edit.operation == Operation::INSERT) {
        chunk_added_lines_count += edit.end - edit.start;
      } else if (edit.operation == Operation::DELETE) {
        chunk_before_lines_count += edit.end - edit.start;
        chunk_added_lines_count -= edit.end - edit.start;
      } else {
        chunk_before_lines_count += edit.end - edit.start;
      }
    }
    const int chunk_after_lines_count =
        chunk_before_lines_count + chunk_added_lines_count;

    // Chunk header
    stream << "@@ -" << (chunk.front().start + 1);
    if (chunk_before_lines_count > 1) stream << "," << chunk_before_lines_count;
    stream << " +" << (chunk.front().start + added_lines_count + 1);
    if (chunk_after_lines_count > 1) stream << "," << chunk_after_lines_count;
    stream << " @@" << std::endl;

    added_lines_count += chunk_added_lines_count;

    for (const auto &edit : chunk) {
      linediffs.PrintEdit(stream, edit);

      // Last line from either original or new text, and final '\n' is missing?
      if ((edit.operation != Operation::INSERT &&
           size_t(edit.end) == linediffs.before_lines.size() &&
           linediffs.before_text.back() != '\n') ||
          (edit.operation == Operation::INSERT &&
           size_t(edit.end) == linediffs.after_lines.size() &&
           linediffs.after_text.back() != '\n')) {
        stream << "\\ No newline at end of file" << std::endl;
      }
    }
  }
}

}  // namespace verible
