//===- InterfaceFile.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
//
//===----------------------------------------------------------------------===//
//
// Implements the Interface File.
//
//===----------------------------------------------------------------------===//

#include "llvm/TextAPI/InterfaceFile.h"
#include "llvm/TextAPI/TextAPIError.h"
#include <iomanip>
#include <sstream>

using namespace llvm;
using namespace llvm::MachO;

void InterfaceFileRef::addTarget(const Target &Target) {
  addEntry(Targets, Target);
}

void InterfaceFile::addAllowableClient(StringRef InstallName,
                                       const Target &Target) {
  auto Client = addEntry(AllowableClients, InstallName);
  Client->addTarget(Target);
}

void InterfaceFile::addReexportedLibrary(StringRef InstallName,
                                         const Target &Target) {
  auto Lib = addEntry(ReexportedLibraries, InstallName);
  Lib->addTarget(Target);
}

void InterfaceFile::addParentUmbrella(const Target &Target_, StringRef Parent) {
  auto Iter = lower_bound(ParentUmbrellas, Target_,
                          [](const std::pair<Target, std::string> &LHS,
                             Target RHS) { return LHS.first < RHS; });

  if ((Iter != ParentUmbrellas.end()) && !(Target_ < Iter->first)) {
    Iter->second = std::string(Parent);
    return;
  }

  ParentUmbrellas.emplace(Iter, Target_, std::string(Parent));
}

void InterfaceFile::addRPath(const Target &InputTarget, StringRef RPath) {
  using RPathEntryT = const std::pair<Target, std::string>;
  RPathEntryT Entry(InputTarget, RPath);
  auto Iter =
      lower_bound(RPaths, Entry,
                  [](RPathEntryT &LHS, RPathEntryT &RHS) { return LHS < RHS; });

  if ((Iter != RPaths.end()) && (*Iter == Entry))
    return;

  RPaths.emplace(Iter, Entry);
}

void InterfaceFile::addTarget(const Target &Target) {
  addEntry(Targets, Target);
}

InterfaceFile::const_filtered_target_range
InterfaceFile::targets(ArchitectureSet Archs) const {
  std::function<bool(const Target &)> fn = [Archs](const Target &Target_) {
    return Archs.has(Target_.Arch);
  };
  return make_filter_range(Targets, fn);
}

void InterfaceFile::addDocument(std::shared_ptr<InterfaceFile> &&Document) {
  auto Pos = llvm::lower_bound(Documents, Document,
                               [](const std::shared_ptr<InterfaceFile> &LHS,
                                  const std::shared_ptr<InterfaceFile> &RHS) {
                                 return LHS->InstallName < RHS->InstallName;
                               });
  Document->Parent = this;
  Documents.insert(Pos, Document);
}

void InterfaceFile::inlineLibrary(std::shared_ptr<InterfaceFile> Library,
                                  bool Overwrite) {
  auto AddFwk = [&](std::shared_ptr<InterfaceFile> &&Reexport) {
    auto It = lower_bound(
        Documents, Reexport->getInstallName(),
        [](std::shared_ptr<InterfaceFile> &Lhs, const StringRef Rhs) {
          return Lhs->getInstallName() < Rhs;
        });

    if (Overwrite && It != Documents.end() &&
        Reexport->getInstallName() == (*It)->getInstallName()) {
      std::replace(Documents.begin(), Documents.end(), *It,
                   std::move(Reexport));
      return;
    }

    if ((It != Documents.end()) &&
        !(Reexport->getInstallName() < (*It)->getInstallName()))
      return;

    Documents.emplace(It, std::move(Reexport));
  };
  for (auto Doc : Library->documents())
    AddFwk(std::move(Doc));

  Library->Documents.clear();
  AddFwk(std::move(Library));
}

Expected<std::unique_ptr<InterfaceFile>>
InterfaceFile::merge(const InterfaceFile *O) const {
  // Verify files can be merged.
  if (getInstallName() != O->getInstallName()) {
    return make_error<StringError>("install names do not match",
                                   inconvertibleErrorCode());
  }

  if (getCurrentVersion() != O->getCurrentVersion()) {
    return make_error<StringError>("current versions do not match",
                                   inconvertibleErrorCode());
  }

  if (getCompatibilityVersion() != O->getCompatibilityVersion()) {
    return make_error<StringError>("compatibility versions do not match",
                                   inconvertibleErrorCode());
  }

  if ((getSwiftABIVersion() != 0) && (O->getSwiftABIVersion() != 0) &&
      (getSwiftABIVersion() != O->getSwiftABIVersion())) {
    return make_error<StringError>("swift ABI versions do not match",
                                   inconvertibleErrorCode());
  }

  if (isTwoLevelNamespace() != O->isTwoLevelNamespace()) {
    return make_error<StringError>("two level namespace flags do not match",
                                   inconvertibleErrorCode());
  }

  if (isApplicationExtensionSafe() != O->isApplicationExtensionSafe()) {
    return make_error<StringError>(
        "application extension safe flags do not match",
        inconvertibleErrorCode());
  }

  std::unique_ptr<InterfaceFile> IF(new InterfaceFile());
  IF->setFileType(std::max(getFileType(), O->getFileType()));
  IF->setPath(getPath());
  IF->setInstallName(getInstallName());
  IF->setCurrentVersion(getCurrentVersion());
  IF->setCompatibilityVersion(getCompatibilityVersion());

  if (getSwiftABIVersion() == 0)
    IF->setSwiftABIVersion(O->getSwiftABIVersion());
  else
    IF->setSwiftABIVersion(getSwiftABIVersion());

  IF->setTwoLevelNamespace(isTwoLevelNamespace());
  IF->setApplicationExtensionSafe(isApplicationExtensionSafe());

  for (const auto &It : umbrellas()) {
    if (!It.second.empty())
      IF->addParentUmbrella(It.first, It.second);
  }
  for (const auto &It : O->umbrellas()) {
    if (!It.second.empty())
      IF->addParentUmbrella(It.first, It.second);
  }
  IF->addTargets(targets());
  IF->addTargets(O->targets());

  for (const auto &Lib : allowableClients())
    for (const auto &Target : Lib.targets())
      IF->addAllowableClient(Lib.getInstallName(), Target);

  for (const auto &Lib : O->allowableClients())
    for (const auto &Target : Lib.targets())
      IF->addAllowableClient(Lib.getInstallName(), Target);

  for (const auto &Lib : reexportedLibraries())
    for (const auto &Target : Lib.targets())
      IF->addReexportedLibrary(Lib.getInstallName(), Target);

  for (const auto &Lib : O->reexportedLibraries())
    for (const auto &Target : Lib.targets())
      IF->addReexportedLibrary(Lib.getInstallName(), Target);

  for (const auto &[Target, Path] : rpaths())
    IF->addRPath(Target, Path);
  for (const auto &[Target, Path] : O->rpaths())
    IF->addRPath(Target, Path);

  for (const auto *Sym : symbols()) {
    IF->addSymbol(Sym->getKind(), Sym->getName(), Sym->targets(),
                  Sym->getFlags());
  }

  for (const auto *Sym : O->symbols()) {
    IF->addSymbol(Sym->getKind(), Sym->getName(), Sym->targets(),
                  Sym->getFlags());
  }

  return std::move(IF);
}

Expected<std::unique_ptr<InterfaceFile>>
InterfaceFile::remove(Architecture Arch) const {
  if (getArchitectures() == Arch)
    return make_error<StringError>("cannot remove last architecture slice '" +
                                       getArchitectureName(Arch) + "'",
                                   inconvertibleErrorCode());

  if (!getArchitectures().has(Arch)) {
    bool Found = false;
    for (auto &Doc : Documents) {
      if (Doc->getArchitectures().has(Arch)) {
        Found = true;
        break;
      }
    }

    if (!Found)
      return make_error<TextAPIError>(TextAPIErrorCode::NoSuchArchitecture);
  }

  std::unique_ptr<InterfaceFile> IF(new InterfaceFile());
  IF->setFileType(getFileType());
  IF->setPath(getPath());
  IF->addTargets(targets(ArchitectureSet::All().clear(Arch)));
  IF->setInstallName(getInstallName());
  IF->setCurrentVersion(getCurrentVersion());
  IF->setCompatibilityVersion(getCompatibilityVersion());
  IF->setSwiftABIVersion(getSwiftABIVersion());
  IF->setTwoLevelNamespace(isTwoLevelNamespace());
  IF->setApplicationExtensionSafe(isApplicationExtensionSafe());
  for (const auto &It : umbrellas())
    if (It.first.Arch != Arch)
      IF->addParentUmbrella(It.first, It.second);

  for (const auto &Lib : allowableClients()) {
    for (const auto &Target : Lib.targets())
      if (Target.Arch != Arch)
        IF->addAllowableClient(Lib.getInstallName(), Target);
  }

  for (const auto &Lib : reexportedLibraries()) {
    for (const auto &Target : Lib.targets())
      if (Target.Arch != Arch)
        IF->addReexportedLibrary(Lib.getInstallName(), Target);
  }

  for (const auto *Sym : symbols()) {
    auto Archs = Sym->getArchitectures();
    Archs.clear(Arch);
    if (Archs.empty())
      continue;

    IF->addSymbol(Sym->getKind(), Sym->getName(), Sym->targets(Archs),
                  Sym->getFlags());
  }

  for (auto &Doc : Documents) {
    // Skip the inlined document if the to be removed architecture is the
    // only one left.
    if (Doc->getArchitectures() == Arch)
      continue;

    // If the document doesn't contain the arch, then no work is to be done
    // and it can be copied over.
    if (!Doc->getArchitectures().has(Arch)) {
      auto NewDoc = Doc;
      IF->addDocument(std::move(NewDoc));
      continue;
    }

    auto Result = Doc->remove(Arch);
    if (!Result)
      return Result;

    IF->addDocument(std::move(Result.get()));
  }

  return std::move(IF);
}

Expected<std::unique_ptr<InterfaceFile>>
InterfaceFile::extract(Architecture Arch) const {
  if (!getArchitectures().has(Arch)) {
    return make_error<StringError>("file doesn't have architecture '" +
                                       getArchitectureName(Arch) + "'",
                                   inconvertibleErrorCode());
  }

  std::unique_ptr<InterfaceFile> IF(new InterfaceFile());
  IF->setFileType(getFileType());
  IF->setPath(getPath());
  IF->addTargets(targets(Arch));
  IF->setInstallName(getInstallName());
  IF->setCurrentVersion(getCurrentVersion());
  IF->setCompatibilityVersion(getCompatibilityVersion());
  IF->setSwiftABIVersion(getSwiftABIVersion());
  IF->setTwoLevelNamespace(isTwoLevelNamespace());
  IF->setApplicationExtensionSafe(isApplicationExtensionSafe());
  for (const auto &It : umbrellas())
    if (It.first.Arch == Arch)
      IF->addParentUmbrella(It.first, It.second);

  for (const auto &It : rpaths())
    if (It.first.Arch == Arch)
      IF->addRPath(It.first, It.second);

  for (const auto &Lib : allowableClients())
    for (const auto &Target : Lib.targets())
      if (Target.Arch == Arch)
        IF->addAllowableClient(Lib.getInstallName(), Target);

  for (const auto &Lib : reexportedLibraries())
    for (const auto &Target : Lib.targets())
      if (Target.Arch == Arch)
        IF->addReexportedLibrary(Lib.getInstallName(), Target);

  for (const auto *Sym : symbols()) {
    if (Sym->hasArchitecture(Arch))
      IF->addSymbol(Sym->getKind(), Sym->getName(), Sym->targets(Arch),
                    Sym->getFlags());
  }

  for (auto &Doc : Documents) {
    // Skip documents that don't have the requested architecture.
    if (!Doc->getArchitectures().has(Arch))
      continue;

    auto Result = Doc->extract(Arch);
    if (!Result)
      return Result;

    IF->addDocument(std::move(Result.get()));
  }

  return std::move(IF);
}

static bool isYAMLTextStub(const FileType &Kind) {
  return (Kind >= FileType::TBD_V1) && (Kind < FileType::TBD_V5);
}

bool InterfaceFile::operator==(const InterfaceFile &O) const {
  if (Targets != O.Targets)
    return false;
  if (InstallName != O.InstallName)
    return false;
  if ((CurrentVersion != O.CurrentVersion) ||
      (CompatibilityVersion != O.CompatibilityVersion))
    return false;
  if (SwiftABIVersion != O.SwiftABIVersion)
    return false;
  if (IsTwoLevelNamespace != O.IsTwoLevelNamespace)
    return false;
  if (IsAppExtensionSafe != O.IsAppExtensionSafe)
    return false;
  if (HasSimSupport != O.HasSimSupport)
    return false;
  if (ParentUmbrellas != O.ParentUmbrellas)
    return false;
  if (AllowableClients != O.AllowableClients)
    return false;
  if (ReexportedLibraries != O.ReexportedLibraries)
    return false;
  if (*SymbolsSet != *O.SymbolsSet)
    return false;
  // Don't compare run search paths for older filetypes that cannot express
  // them.
  if (!(isYAMLTextStub(FileKind)) && !(isYAMLTextStub(O.FileKind))) {
    if (RPaths != O.RPaths)
      return false;
    if (mapToPlatformVersionSet(Targets) != mapToPlatformVersionSet(O.Targets))
      return false;
  }

  if (!std::equal(Documents.begin(), Documents.end(), O.Documents.begin(),
                  O.Documents.end(),
                  [](const std::shared_ptr<InterfaceFile> LHS,
                     const std::shared_ptr<InterfaceFile> RHS) {
                    return *LHS == *RHS;
                  }))
    return false;
  return true;
}
