//===- 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/RecordsSlice.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) {
  if (InstallName.empty())
    return;
  auto Client = addEntry(AllowableClients, InstallName);
  Client->addTarget(Target);
}

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

void InterfaceFile::addParentUmbrella(const Target &Target_, StringRef Parent) {
  if (Parent.empty())
    return;
  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(StringRef RPath, const Target &InputTarget) {
  if (RPath.empty())
    return;
  using RPathEntryT = const std::pair<Target, std::string>;
  RPathEntryT Entry(InputTarget, RPath);

  if (is_contained(RPaths, Entry))
    return;

  RPaths.emplace_back(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;
                               });
  assert((Pos == Documents.end() ||
          (*Pos)->InstallName != Document->InstallName) &&
         "Unexpected duplicate document added");
  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()) {
      llvm::replace(Documents, *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());
  IF->setOSLibNotForSharedCache(isOSLibNotForSharedCache());

  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(Path, Target);
  for (const auto &[Target, Path] : O->rpaths())
    IF->addRPath(Path, Target);

  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);
  }

  // FIXME: Figure out how to keep these attributes in sync when new ones are
  // added.
  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());
  IF->setOSLibNotForSharedCache(isOSLibNotForSharedCache());
  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());
  IF->setOSLibNotForSharedCache(isOSLibNotForSharedCache());
  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.second, It.first);

  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);
}

void InterfaceFile::setFromBinaryAttrs(const RecordsSlice::BinaryAttrs &BA,
                                       const Target &Targ) {
  if (getFileType() != BA.File)
    setFileType(BA.File);
  if (getInstallName().empty())
    setInstallName(BA.InstallName);
  if (BA.AppExtensionSafe && !isApplicationExtensionSafe())
    setApplicationExtensionSafe();
  if (BA.TwoLevelNamespace && !isTwoLevelNamespace())
    setTwoLevelNamespace();
  if (BA.OSLibNotForSharedCache && !isOSLibNotForSharedCache())
    setOSLibNotForSharedCache();
  if (getCurrentVersion().empty())
    setCurrentVersion(BA.CurrentVersion);
  if (getCompatibilityVersion().empty())
    setCompatibilityVersion(BA.CompatVersion);
  if (getSwiftABIVersion() == 0)
    setSwiftABIVersion(BA.SwiftABI);
  if (getPath().empty())
    setPath(BA.Path);
  if (!BA.ParentUmbrella.empty())
    addParentUmbrella(Targ, BA.ParentUmbrella);
  for (const auto &Client : BA.AllowableClients)
    addAllowableClient(Client, Targ);
  for (const auto &Lib : BA.RexportedLibraries)
    addReexportedLibrary(Lib, Targ);
}

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 (IsOSLibNotForSharedCache != O.IsOSLibNotForSharedCache)
    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;
}
