//===--- PathMapping.cpp - apply path mappings to LSP messages -===//
//
// 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 "PathMapping.h"
#include "Transport.h"
#include "URI.h"
#include "support/Logger.h"
#include "llvm/ADT/None.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/Errno.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/Path.h"
#include <algorithm>
#include <tuple>

namespace clang {
namespace clangd {
llvm::Optional<std::string> doPathMapping(llvm::StringRef S,
                                          PathMapping::Direction Dir,
                                          const PathMappings &Mappings) {
  // Return early to optimize for the common case, wherein S is not a file URI
  if (!S.startswith("file://"))
    return llvm::None;
  auto Uri = URI::parse(S);
  if (!Uri) {
    llvm::consumeError(Uri.takeError());
    return llvm::None;
  }
  for (const auto &Mapping : Mappings) {
    const std::string &From = Dir == PathMapping::Direction::ClientToServer
                                  ? Mapping.ClientPath
                                  : Mapping.ServerPath;
    const std::string &To = Dir == PathMapping::Direction::ClientToServer
                                ? Mapping.ServerPath
                                : Mapping.ClientPath;
    llvm::StringRef Body = Uri->body();
    if (Body.consume_front(From) && (Body.empty() || Body.front() == '/')) {
      std::string MappedBody = (To + Body).str();
      return URI(Uri->scheme(), Uri->authority(), MappedBody)
          .toString();
    }
  }
  return llvm::None;
}

void applyPathMappings(llvm::json::Value &V, PathMapping::Direction Dir,
                       const PathMappings &Mappings) {
  using Kind = llvm::json::Value::Kind;
  Kind K = V.kind();
  if (K == Kind::Object) {
    llvm::json::Object *Obj = V.getAsObject();
    llvm::json::Object MappedObj;
    // 1. Map all the Keys
    for (auto &KV : *Obj) {
      if (llvm::Optional<std::string> MappedKey =
              doPathMapping(KV.first.str(), Dir, Mappings)) {
        MappedObj.try_emplace(std::move(*MappedKey), std::move(KV.second));
      } else {
        MappedObj.try_emplace(std::move(KV.first), std::move(KV.second));
      }
    }
    *Obj = std::move(MappedObj);
    // 2. Map all the values
    for (auto &KV : *Obj)
      applyPathMappings(KV.second, Dir, Mappings);
  } else if (K == Kind::Array) {
    for (llvm::json::Value &Val : *V.getAsArray())
      applyPathMappings(Val, Dir, Mappings);
  } else if (K == Kind::String) {
    if (llvm::Optional<std::string> Mapped =
            doPathMapping(*V.getAsString(), Dir, Mappings))
      V = std::move(*Mapped);
  }
}

namespace {

class PathMappingMessageHandler : public Transport::MessageHandler {
public:
  PathMappingMessageHandler(MessageHandler &Handler,
                            const PathMappings &Mappings)
      : WrappedHandler(Handler), Mappings(Mappings) {}

  bool onNotify(llvm::StringRef Method, llvm::json::Value Params) override {
    applyPathMappings(Params, PathMapping::Direction::ClientToServer, Mappings);
    return WrappedHandler.onNotify(Method, std::move(Params));
  }

  bool onCall(llvm::StringRef Method, llvm::json::Value Params,
              llvm::json::Value ID) override {
    applyPathMappings(Params, PathMapping::Direction::ClientToServer, Mappings);
    return WrappedHandler.onCall(Method, std::move(Params), std::move(ID));
  }

  bool onReply(llvm::json::Value ID,
               llvm::Expected<llvm::json::Value> Result) override {
    if (Result)
      applyPathMappings(*Result, PathMapping::Direction::ClientToServer,
                        Mappings);
    return WrappedHandler.onReply(std::move(ID), std::move(Result));
  }

private:
  Transport::MessageHandler &WrappedHandler;
  const PathMappings &Mappings;
};

// Apply path mappings to all LSP messages by intercepting all params/results
// and then delegating to the normal transport
class PathMappingTransport : public Transport {
public:
  PathMappingTransport(std::unique_ptr<Transport> Transp, PathMappings Mappings)
      : WrappedTransport(std::move(Transp)), Mappings(std::move(Mappings)) {}

  void notify(llvm::StringRef Method, llvm::json::Value Params) override {
    applyPathMappings(Params, PathMapping::Direction::ServerToClient, Mappings);
    WrappedTransport->notify(Method, std::move(Params));
  }

  void call(llvm::StringRef Method, llvm::json::Value Params,
            llvm::json::Value ID) override {
    applyPathMappings(Params, PathMapping::Direction::ServerToClient, Mappings);
    WrappedTransport->call(Method, std::move(Params), std::move(ID));
  }

  void reply(llvm::json::Value ID,
             llvm::Expected<llvm::json::Value> Result) override {
    if (Result)
      applyPathMappings(*Result, PathMapping::Direction::ServerToClient,
                        Mappings);
    WrappedTransport->reply(std::move(ID), std::move(Result));
  }

  llvm::Error loop(MessageHandler &Handler) override {
    PathMappingMessageHandler WrappedHandler(Handler, Mappings);
    return WrappedTransport->loop(WrappedHandler);
  }

private:
  std::unique_ptr<Transport> WrappedTransport;
  PathMappings Mappings;
};

// Converts a unix/windows path to the path portion of a file URI
// e.g. "C:\foo" -> "/C:/foo"
llvm::Expected<std::string> parsePath(llvm::StringRef Path) {
  namespace path = llvm::sys::path;
  if (path::is_absolute(Path, path::Style::posix)) {
    return std::string(Path);
  }
  if (path::is_absolute(Path, path::Style::windows)) {
    std::string Converted = path::convert_to_slash(Path, path::Style::windows);
    if (Converted.front() != '/')
      Converted = "/" + Converted;
    return Converted;
  }
  return error("Path not absolute: {0}", Path);
}

} // namespace

llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const PathMapping &M) {
  return OS << M.ClientPath << "=" << M.ServerPath;
}

llvm::Expected<PathMappings>
parsePathMappings(llvm::StringRef RawPathMappings) {
  llvm::StringRef ClientPath, ServerPath, PathPair, Rest = RawPathMappings;
  PathMappings ParsedMappings;
  while (!Rest.empty()) {
    std::tie(PathPair, Rest) = Rest.split(",");
    std::tie(ClientPath, ServerPath) = PathPair.split("=");
    if (ClientPath.empty() || ServerPath.empty())
      return error("Not a valid path mapping pair: {0}", PathPair);
    llvm::Expected<std::string> ParsedClientPath = parsePath(ClientPath);
    if (!ParsedClientPath)
      return ParsedClientPath.takeError();
    llvm::Expected<std::string> ParsedServerPath = parsePath(ServerPath);
    if (!ParsedServerPath)
      return ParsedServerPath.takeError();
    ParsedMappings.push_back(
        {std::move(*ParsedClientPath), std::move(*ParsedServerPath)});
  }
  return ParsedMappings;
}

std::unique_ptr<Transport>
createPathMappingTransport(std::unique_ptr<Transport> Transp,
                           PathMappings Mappings) {
  return std::make_unique<PathMappingTransport>(std::move(Transp), Mappings);
}

} // namespace clangd
} // namespace clang
