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

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

#include "absl/strings/str_cat.h"
#include "absl/strings/string_view.h"
#include "common/strings/line_column_map.h"
#include "common/text/concrete_syntax_leaf.h"
#include "common/text/symbol.h"
#include "common/text/syntax_tree_context.h"
#include "common/text/token_info.h"
#include "common/text/tree_utils.h"
#include "common/util/spacer.h"

namespace verible {

std::string AutoFix::Apply(const absl::string_view base) const {
  std::string result;
  auto prev_start = base.cbegin();
  for (const auto& edit : edits) {
    CHECK_LE(base.cbegin(), edit.fragment.cbegin());
    CHECK_GE(base.cend(), edit.fragment.cend());

    const absl::string_view text_before(
        prev_start, std::distance(prev_start, edit.fragment.cbegin()));
    absl::StrAppend(&result, text_before, edit.replacement);

    prev_start = edit.fragment.cend();
  }
  const absl::string_view text_after(prev_start,
                                     std::distance(prev_start, base.cend()));
  return absl::StrCat(result, text_after);
}

bool AutoFix::AddEdits(const std::set<ReplacementEdit>& new_edits) {
  // Check for conflicts
  for (const auto& edit : new_edits) {
    if (edits.find(edit) != edits.end()) {
      return false;
    }
  }
  edits.insert(new_edits.cbegin(), new_edits.cend());
  return true;
}

static TokenInfo SymbolToToken(const Symbol& root) {
  const auto* leaf = GetLeftmostLeaf(root);
  if (leaf) {
    return leaf->get();
  }
  // There shouldn't be any leaf-less subtrees.
  return TokenInfo::EOFToken();
}

LintViolation::LintViolation(const Symbol& root, const std::string& reason,
                             const SyntaxTreeContext& context,
                             std::initializer_list<AutoFix> autofixes)
    : root(&root),
      token(SymbolToToken(root)),
      reason(reason),
      context(context),
      autofixes(autofixes) {}

void LintStatusFormatter::FormatLintRuleStatus(std::ostream* stream,
                                               const LintRuleStatus& status,
                                               absl::string_view base,
                                               absl::string_view path) const {
  for (const auto& violation : status.violations) {
    FormatViolation(stream, violation, base, path, status.url,
                    status.lint_rule_name);
    (*stream) << std::endl;
  }
}

struct LintViolationWithStatus {
  const LintViolation* violation;
  const LintRuleStatus* status;

  LintViolationWithStatus(const LintViolation* v, const LintRuleStatus* s)
      : violation(v), status(s) {}

  bool operator<(const LintViolationWithStatus& r) const {
    // compares addresses which correspond to locations within the same string
    return violation->token.text().data() < r.violation->token.text().data();
  }
};

void LintStatusFormatter::FormatLintRuleStatuses(
    std::ostream* stream, const std::vector<LintRuleStatus>& statuses,
    absl::string_view base, absl::string_view path,
    const std::vector<absl::string_view>& lines) const {
  std::set<LintViolationWithStatus> violations;

  // TODO(fangism): rewrite as a linear time merge of pre-ordered sub-sequences
  for (auto& status : statuses) {
    for (auto& violation : status.violations) {
      violations.insert(LintViolationWithStatus(&violation, &status));
    }
  }

  for (auto violation : violations) {
    FormatViolation(stream, *violation.violation, base, path,
                    violation.status->url, violation.status->lint_rule_name);
    if (violation.violation->autofixes.size() > 0) {
      *stream << " (autofix available)";
    }
    *stream << std::endl;
    auto cursor = line_column_map_(violation.violation->token.left(base));
    if (cursor.line < static_cast<int>(lines.size())) {
      *stream << lines[cursor.line] << std::endl;
      *stream << verible::Spacer(cursor.column) << "^" << std::endl;
    }
  }
}

// Formats and outputs violation on stream
// Path is file path of original file and url is a link to violated rule
void LintStatusFormatter::FormatViolation(std::ostream* stream,
                                          const LintViolation& violation,
                                          absl::string_view base,
                                          absl::string_view path,
                                          absl::string_view url,
                                          absl::string_view rule_name) const {
  // TODO(fangism): Use the context member to print which named construct or
  // design element the violation appears in (or full stack thereof).
  (*stream) << path << ':' << line_column_map_(violation.token.left(base))
            << ": " << violation.reason << ' ' << url << " [" << rule_name
            << ']';
}

void LintRuleStatus::WaiveViolations(
    std::function<bool(const LintViolation&)>&& is_waived) {
  std::set<LintViolation> filtered_violations;
  std::remove_copy_if(
      violations.begin(), violations.end(),
      std::inserter(filtered_violations, filtered_violations.begin()),
      is_waived);
  violations.swap(filtered_violations);
}

}  // namespace verible
