//===-- LVCompare.cpp -----------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This implements the LVCompare class.
//
//===----------------------------------------------------------------------===//

#include "llvm/DebugInfo/LogicalView/Core/LVCompare.h"
#include "llvm/DebugInfo/LogicalView/Core/LVOptions.h"
#include "llvm/DebugInfo/LogicalView/Core/LVReader.h"
#include <tuple>

using namespace llvm;
using namespace llvm::logicalview;

#define DEBUG_TYPE "Compare"

namespace {

enum class LVCompareItem { Scope, Symbol, Type, Line, Total };
enum class LVCompareIndex { Header, Expected, Missing, Added };
using LVCompareEntry = std::tuple<const char *, unsigned, unsigned, unsigned>;
using LVCompareInfo = std::map<LVCompareItem, LVCompareEntry>;
LVCompareInfo Results = {
    {LVCompareItem::Line, LVCompareEntry("Lines", 0, 0, 0)},
    {LVCompareItem::Scope, LVCompareEntry("Scopes", 0, 0, 0)},
    {LVCompareItem::Symbol, LVCompareEntry("Symbols", 0, 0, 0)},
    {LVCompareItem::Type, LVCompareEntry("Types", 0, 0, 0)},
    {LVCompareItem::Total, LVCompareEntry("Total", 0, 0, 0)}};
static LVCompareInfo::iterator IterTotal = Results.end();

constexpr unsigned getHeader() {
  return static_cast<unsigned>(LVCompareIndex::Header);
}
constexpr unsigned getExpected() {
  return static_cast<unsigned>(LVCompareIndex::Expected);
}
constexpr unsigned getMissing() {
  return static_cast<unsigned>(LVCompareIndex::Missing);
}
constexpr unsigned getAdded() {
  return static_cast<unsigned>(LVCompareIndex::Added);
}

LVCompare *CurrentComparator = nullptr;

void zeroResults() {
  // In case the same reader instance is used.
  for (LVCompareInfo::reference Entry : Results) {
    std::get<getExpected()>(Entry.second) = 0;
    std::get<getMissing()>(Entry.second) = 0;
    std::get<getAdded()>(Entry.second) = 0;
  }
  IterTotal = Results.find(LVCompareItem::Total);
  assert(IterTotal != Results.end());
}

LVCompareInfo::iterator getResultsEntry(LVElement *Element) {
  LVCompareItem Kind;
  if (Element->getIsLine())
    Kind = LVCompareItem::Line;
  else if (Element->getIsScope())
    Kind = LVCompareItem::Scope;
  else if (Element->getIsSymbol())
    Kind = LVCompareItem::Symbol;
  else
    Kind = LVCompareItem::Type;

  // Used to update the expected, missing or added entry for the given kind.
  LVCompareInfo::iterator Iter = Results.find(Kind);
  assert(Iter != Results.end());
  return Iter;
}

void updateExpected(LVElement *Element) {
  LVCompareInfo::iterator Iter = getResultsEntry(Element);
  // Update total for expected.
  ++std::get<getExpected()>(IterTotal->second);
  // Update total for specific element kind.
  ++std::get<getExpected()>(Iter->second);
}

void updateMissingOrAdded(LVElement *Element, LVComparePass Pass) {
  LVCompareInfo::iterator Iter = getResultsEntry(Element);
  if (Pass == LVComparePass::Missing) {
    ++std::get<getMissing()>(IterTotal->second);
    ++std::get<getMissing()>(Iter->second);
  } else {
    ++std::get<getAdded()>(IterTotal->second);
    ++std::get<getAdded()>(Iter->second);
  }
}

} // namespace

LVCompare &LVCompare::getInstance() {
  static LVCompare DefaultComparator(outs());
  return CurrentComparator ? *CurrentComparator : DefaultComparator;
}

void LVCompare::setInstance(LVCompare *Comparator) {
  CurrentComparator = Comparator;
}

LVCompare::LVCompare(raw_ostream &OS) : OS(OS) {
  PrintLines = options().getPrintLines();
  PrintSymbols = options().getPrintSymbols();
  PrintTypes = options().getPrintTypes();
  PrintScopes =
      options().getPrintScopes() || PrintLines || PrintSymbols || PrintTypes;
}

Error LVCompare::execute(LVReader *ReferenceReader, LVReader *TargetReader) {
  setInstance(this);
  // In the case of added elements, the 'Reference' reader will be modified;
  // those elements will be added to it. Update the current reader instance.
  LVReader::setInstance(ReferenceReader);

  auto PrintHeader = [this](LVScopeRoot *LHS, LVScopeRoot *RHS) {
    LLVM_DEBUG({
      dbgs() << "[Reference] " << LHS->getName() << "\n"
             << "[Target] " << RHS->getName() << "\n";
    });
    OS << "\nReference: " << formattedName(LHS->getName()) << "\n"
       << "Target:    " << formattedName(RHS->getName()) << "\n";
  };

  // We traverse the given scopes tree ('Reference' and 'Target') twice.
  // The first time we look for missing items from the 'Reference' and the
  // second time we look for items added to the 'Target'.
  // The comparison test includes the name, lexical level, type, source
  // location, etc.
  LVScopeRoot *ReferenceRoot = ReferenceReader->getScopesRoot();
  LVScopeRoot *TargetRoot = TargetReader->getScopesRoot();
  ReferenceRoot->setIsInCompare();
  TargetRoot->setIsInCompare();

  // Reset possible previous results.
  zeroResults();

  if (options().getCompareContext()) {
    // Perform a logical view comparison as a whole unit. We start at the
    // root reference; at each scope an equal test is applied to its children.
    // If a difference is found, the current path is marked as missing.
    auto CompareViews = [this](LVScopeRoot *LHS, LVScopeRoot *RHS) -> Error {
      LHS->markMissingParents(RHS, /*TraverseChildren=*/true);
      if (LHS->getIsMissingLink() && options().getReportAnyView()) {
        // As we are printing a missing tree, enable formatting.
        options().setPrintFormatting();
        OS << "\nMissing Tree:\n";
        if (Error Err = LHS->doPrint(/*Split=*/false, /*Match=*/false,
                                     /*Print=*/true, OS))
          return Err;
        options().resetPrintFormatting();
      }

      return Error::success();
    };

    // If the user has requested printing details for the comparison, we
    // disable the indentation and the added/missing tags ('+'/'-'), as the
    // details are just a list of elements.
    options().resetPrintFormatting();

    PrintHeader(ReferenceRoot, TargetRoot);
    Reader = ReferenceReader;
    if (Error Err = CompareViews(ReferenceRoot, TargetRoot))
      return Err;
    FirstMissing = true;
    ReferenceRoot->report(LVComparePass::Missing);

    PrintHeader(TargetRoot, ReferenceRoot);
    Reader = TargetReader;
    if (Error Err = CompareViews(TargetRoot, ReferenceRoot))
      return Err;
    FirstMissing = true;
    TargetRoot->report(LVComparePass::Added);

    options().setPrintFormatting();

    // Display a summary with the elements missing and/or added.
    printSummary();
  } else {
    // Perform logical elements comparison. An equal test is apply to each
    // element. If a difference is found, the reference element is marked as
    // 'missing'.
    // The final comparison result will show the 'Reference' scopes tree,
    // having both missing and added elements.
    using LVScopeLink = std::map<LVScope *, LVScope *>;
    LVScopeLink ScopeLinks;
    auto CompareReaders = [&](LVReader *LHS, LVReader *RHS, LVElements &Set,
                              LVComparePass Pass) -> Error {
      auto FindMatch = [&](auto &References, auto &Targets,
                           const char *Category) -> Error {
        LVElements Elements;
        for (LVElement *Reference : References) {
          // Report elements that can be printed; ignore logical elements that
          // have qualifiers.
          if (Reference->getIncludeInPrint()) {
            if (Pass == LVComparePass::Missing)
              updateExpected(Reference);
            Reference->setIsInCompare();
            LVElement *CurrentTarget = nullptr;
            if (std::any_of(Targets.begin(), Targets.end(),
                            [&](auto Target) -> bool {
                              CurrentTarget = Target;
                              return Reference->equals(Target);
                            })) {
              if (Pass == LVComparePass::Missing && Reference->getIsScope()) {
                // If the elements being compared are scopes and are a match,
                // they are recorded, to be used when creating the augmented
                // tree, as insertion points for the "added" items.
                ScopeLinks.emplace(static_cast<LVScope *>(CurrentTarget),
                                   static_cast<LVScope *>(Reference));
              }
            } else {
              // Element is missing or added.
              Pass == LVComparePass::Missing ? Reference->setIsMissing()
                                             : Reference->setIsAdded();
              Elements.push_back(Reference);
              updateMissingOrAdded(Reference, Pass);
              // Record missing/added element.
              addPassEntry(Reader, Reference, Pass);
            }
          }
        }
        if (Pass == LVComparePass::Added)
          // Record all the current missing elements for this category.
          Set.insert(Set.end(), Elements.begin(), Elements.end());
        if (options().getReportList()) {
          if (Elements.size()) {
            OS << "\n(" << Elements.size() << ") "
               << (Pass == LVComparePass::Missing ? "Missing" : "Added") << " "
               << Category << ":\n";
            for (const LVElement *Element : Elements) {
              if (Error Err = Element->doPrint(/*Split=*/false, /*Match=*/false,
                                               /*Print=*/true, OS))
                return Err;
            }
          }
        }

        return Error::success();
      };

      // First compare the scopes, so they will be inserted at the front of
      // the missing elements list. When they are moved, their children are
      // moved as well and no additional work is required.
      if (options().getCompareScopes())
        if (Error Err = FindMatch(LHS->getScopes(), RHS->getScopes(), "Scopes"))
          return Err;
      if (options().getCompareSymbols())
        if (Error Err =
                FindMatch(LHS->getSymbols(), RHS->getSymbols(), "Symbols"))
          return Err;
      if (options().getCompareTypes())
        if (Error Err = FindMatch(LHS->getTypes(), RHS->getTypes(), "Types"))
          return Err;
      if (options().getCompareLines())
        if (Error Err = FindMatch(LHS->getLines(), RHS->getLines(), "Lines"))
          return Err;

      return Error::success();
    };

    // If the user has requested printing details for the comparison, we
    // disable the indentation and the added/missing tags ('+'/'-'), as the
    // details are just a list of elements.
    options().resetPrintFormatting();

    PrintHeader(ReferenceRoot, TargetRoot);
    // Include the root in the expected count.
    updateExpected(ReferenceRoot);

    LVElements ElementsToAdd;
    Reader = ReferenceReader;
    if (Error Err = CompareReaders(ReferenceReader, TargetReader, ElementsToAdd,
                                   LVComparePass::Missing))
      return Err;
    Reader = TargetReader;
    if (Error Err = CompareReaders(TargetReader, ReferenceReader, ElementsToAdd,
                                   LVComparePass::Added))
      return Err;

    LLVM_DEBUG({
      dbgs() << "\nReference/Target Scope links:\n";
      for (LVScopeLink::const_reference Entry : ScopeLinks)
        dbgs() << "Source: " << hexSquareString(Entry.first->getOffset()) << " "
               << "Destination: " << hexSquareString(Entry.second->getOffset())
               << "\n";
      dbgs() << "\n";
    });

    // Add the 'missing' elements from the 'Target' into the 'Reference'.
    // First insert the missing scopes, as they include any missing children.
    LVScope *Parent = nullptr;
    for (LVElement *Element : ElementsToAdd) {
      LLVM_DEBUG({
        dbgs() << "Element to Insert: " << hexSquareString(Element->getOffset())
               << ", Parent: "
               << hexSquareString(Element->getParentScope()->getOffset())
               << "\n";
      });
      // Skip already inserted elements. They were inserted, if their parents
      // were missing. When inserting them, all the children are moved.
      if (Element->getHasMoved())
        continue;

      // We need to find an insertion point in the reference scopes tree.
      Parent = Element->getParentScope();
      if (ScopeLinks.find(Parent) != ScopeLinks.end()) {
        LVScope *InsertionPoint = ScopeLinks[Parent];
        LLVM_DEBUG({
          dbgs() << "Inserted at: "
                 << hexSquareString(InsertionPoint->getOffset()) << "\n";
        });
        if (Parent->removeElement(Element)) {
          // Be sure we have a current compile unit.
          getReader().setCompileUnit(InsertionPoint->getCompileUnitParent());
          InsertionPoint->addElement(Element);
          Element->updateLevel(InsertionPoint, /*Moved=*/true);
        }
      }
    }

    options().setPrintFormatting();

    // Display the augmented reference scopes tree.
    if (options().getReportAnyView())
      if (Error Err = ReferenceReader->doPrint())
        return Err;

    LLVM_DEBUG({
      dbgs() << "\nModified Reference Reader";
      if (Error Err = ReferenceReader->doPrint())
        return Err;
      dbgs() << "\nModified Target Reader";
      if (Error Err = TargetReader->doPrint())
        return Err;
    });

    // Display a summary with the elements missing and/or added.
    printSummary();
  }

  return Error::success();
}

void LVCompare::printCurrentStack() {
  for (const LVScope *Scope : ScopeStack) {
    Scope->printAttributes(OS);
    OS << Scope->lineNumberAsString(/*ShowZero=*/true) << " " << Scope->kind()
       << " " << formattedName(Scope->getName()) << "\n";
  }
}

void LVCompare::printItem(LVElement *Element, LVComparePass Pass) {
  // Record expected, missing, added.
  updateExpected(Element);
  updateMissingOrAdded(Element, Pass);

  // Record missing/added element.
  if (Element->getIsMissing())
    addPassEntry(Reader, Element, Pass);

  if ((!PrintLines && Element->getIsLine()) ||
      (!PrintScopes && Element->getIsScope()) ||
      (!PrintSymbols && Element->getIsSymbol()) ||
      (!PrintTypes && Element->getIsType()))
    return;

  if (Element->getIsMissing()) {
    if (FirstMissing) {
      OS << "\n";
      FirstMissing = false;
    }

    StringRef Kind = Element->kind();
    StringRef Name =
        Element->getIsLine() ? Element->getPathname() : Element->getName();
    StringRef Status = (Pass == LVComparePass::Missing) ? "Missing" : "Added";
    OS << Status << " " << Kind << " '" << Name << "'";
    if (Element->getLineNumber() > 0)
      OS << " at line " << Element->getLineNumber();
    OS << "\n";

    if (options().getReportList()) {
      printCurrentStack();
      Element->printAttributes(OS);
      OS << Element->lineNumberAsString(/*ShowZero=*/true) << " " << Kind << " "
         << Name << "\n";
    }
  }
}

void LVCompare::printSummary() const {
  if (!options().getPrintSummary())
    return;
  std::string Separator = std::string(40, '-');
  auto PrintSeparator = [&]() { OS << Separator << "\n"; };
  auto PrintHeadingRow = [&](const char *T, const char *U, const char *V,
                             const char *W) {
    OS << format("%-9s%9s  %9s  %9s\n", T, U, V, W);
  };
  auto PrintDataRow = [&](const char *T, unsigned U, unsigned V, unsigned W) {
    OS << format("%-9s%9d  %9d  %9d\n", T, U, V, W);
  };

  OS << "\n";
  PrintSeparator();
  PrintHeadingRow("Element", "Expected", "Missing", "Added");
  PrintSeparator();
  for (LVCompareInfo::reference Entry : Results) {
    if (Entry.first == LVCompareItem::Total)
      PrintSeparator();
    PrintDataRow(std::get<getHeader()>(Entry.second),
                 std::get<getExpected()>(Entry.second),
                 std::get<getMissing()>(Entry.second),
                 std::get<getAdded()>(Entry.second));
  }
}

void LVCompare::print(raw_ostream &OS) const { OS << "LVCompare\n"; }
