//===--- ConfigProvider.cpp - Loading of user configuration ---------------===//
//
// 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
//
//===----------------------------------------------------------------------===//

#include "ConfigProvider.h"
#include "Config.h"
#include "ConfigFragment.h"
#include "support/FileCache.h"
#include "support/Path.h"
#include "support/ThreadsafeFS.h"
#include "support/Trace.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Path.h"
#include <chrono>
#include <mutex>
#include <string>

namespace clang {
namespace clangd {
namespace config {

// Threadsafe cache around reading a YAML config file from disk.
class FileConfigCache : public FileCache {
  mutable llvm::SmallVector<CompiledFragment, 1> CachedValue;
  std::string Directory;

public:
  FileConfigCache(llvm::StringRef Path, llvm::StringRef Directory)
      : FileCache(Path), Directory(Directory) {}

  void get(const ThreadsafeFS &TFS, DiagnosticCallback DC,
           std::chrono::steady_clock::time_point FreshTime, bool Trusted,
           std::vector<CompiledFragment> &Out) const {
    read(
        TFS, FreshTime,
        [&](llvm::Optional<llvm::StringRef> Data) {
          CachedValue.clear();
          if (Data)
            for (auto &Fragment : Fragment::parseYAML(*Data, path(), DC)) {
              Fragment.Source.Directory = Directory;
              Fragment.Source.Trusted = Trusted;
              CachedValue.push_back(std::move(Fragment).compile(DC));
            }
        },
        [&]() { llvm::copy(CachedValue, std::back_inserter(Out)); });
  }
};

std::unique_ptr<Provider> Provider::fromYAMLFile(llvm::StringRef AbsPath,
                                                 llvm::StringRef Directory,
                                                 const ThreadsafeFS &FS,
                                                 bool Trusted) {
  class AbsFileProvider : public Provider {
    mutable FileConfigCache Cache; // threadsafe
    const ThreadsafeFS &FS;
    bool Trusted;

    std::vector<CompiledFragment>
    getFragments(const Params &P, DiagnosticCallback DC) const override {
      std::vector<CompiledFragment> Result;
      Cache.get(FS, DC, P.FreshTime, Trusted, Result);
      return Result;
    };

  public:
    AbsFileProvider(llvm::StringRef Path, llvm::StringRef Directory,
                    const ThreadsafeFS &FS, bool Trusted)
        : Cache(Path, Directory), FS(FS), Trusted(Trusted) {
      assert(llvm::sys::path::is_absolute(Path));
    }
  };

  return std::make_unique<AbsFileProvider>(AbsPath, Directory, FS, Trusted);
}

std::unique_ptr<Provider>
Provider::fromAncestorRelativeYAMLFiles(llvm::StringRef RelPath,
                                        const ThreadsafeFS &FS, bool Trusted) {
  class RelFileProvider : public Provider {
    std::string RelPath;
    const ThreadsafeFS &FS;
    bool Trusted;

    mutable std::mutex Mu;
    // Keys are the (posix-style) ancestor directory, not the config within it.
    // We only insert into this map, so pointers to values are stable forever.
    // Mutex guards the map itself, not the values (which are threadsafe).
    mutable llvm::StringMap<FileConfigCache> Cache;

    std::vector<CompiledFragment>
    getFragments(const Params &P, DiagnosticCallback DC) const override {
      namespace path = llvm::sys::path;

      if (P.Path.empty())
        return {};

      // Compute absolute paths to all ancestors (substrings of P.Path).
      llvm::SmallVector<llvm::StringRef, 8> Ancestors;
      for (auto Ancestor = absoluteParent(P.Path); !Ancestor.empty();
           Ancestor = absoluteParent(Ancestor)) {
        Ancestors.emplace_back(Ancestor);
      }
      // Ensure corresponding cache entries exist in the map.
      llvm::SmallVector<FileConfigCache *, 8> Caches;
      {
        std::lock_guard<std::mutex> Lock(Mu);
        for (llvm::StringRef Ancestor : Ancestors) {
          auto It = Cache.find(Ancestor);
          // Assemble the actual config file path only once.
          if (It == Cache.end()) {
            llvm::SmallString<256> ConfigPath = Ancestor;
            path::append(ConfigPath, RelPath);
            // Use native slashes for reading the file, affects diagnostics.
            llvm::sys::path::native(ConfigPath);
            It = Cache.try_emplace(Ancestor, ConfigPath.str(), Ancestor).first;
          }
          Caches.push_back(&It->second);
        }
      }
      // Finally query each individual file.
      // This will take a (per-file) lock for each file that actually exists.
      std::vector<CompiledFragment> Result;
      for (FileConfigCache *Cache : llvm::reverse(Caches))
        Cache->get(FS, DC, P.FreshTime, Trusted, Result);
      return Result;
    };

  public:
    RelFileProvider(llvm::StringRef RelPath, const ThreadsafeFS &FS,
                    bool Trusted)
        : RelPath(RelPath), FS(FS), Trusted(Trusted) {
      assert(llvm::sys::path::is_relative(RelPath));
    }
  };

  return std::make_unique<RelFileProvider>(RelPath, FS, Trusted);
}

std::unique_ptr<Provider>
Provider::combine(std::vector<const Provider *> Providers) {
  class CombinedProvider : public Provider {
    std::vector<const Provider *> Providers;

    std::vector<CompiledFragment>
    getFragments(const Params &P, DiagnosticCallback DC) const override {
      std::vector<CompiledFragment> Result;
      for (const auto &Provider : Providers) {
        for (auto &Fragment : Provider->getFragments(P, DC))
          Result.push_back(std::move(Fragment));
      }
      return Result;
    }

  public:
    CombinedProvider(std::vector<const Provider *> Providers)
        : Providers(std::move(Providers)) {}
  };

  return std::make_unique<CombinedProvider>(std::move(Providers));
}

Config Provider::getConfig(const Params &P, DiagnosticCallback DC) const {
  trace::Span Tracer("getConfig");
  if (!P.Path.empty())
    SPAN_ATTACH(Tracer, "path", P.Path);
  Config C;
  for (const auto &Fragment : getFragments(P, DC))
    Fragment(P, C);
  return C;
}

} // namespace config
} // namespace clangd
} // namespace clang
