// 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 <iterator>
#include <ostream>
#include <string>
#include <vector>

#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"

namespace verible {

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)
    : root(&root),
      token(SymbolToToken(root)),
      reason(reason),
      context(context) {}

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::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);
    *stream << 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
