//===--- OutputFileMap.cpp - Driver output file map -----------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//

#include "swift/Driver/OutputFileMap.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/raw_ostream.h"
#include <system_error>

using namespace swift;
using namespace swift::driver;

std::unique_ptr<OutputFileMap> OutputFileMap::loadFromPath(StringRef Path) {
  llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> FileBufOrErr =
    llvm::MemoryBuffer::getFile(Path);
  if (!FileBufOrErr)
    return nullptr;
  return loadFromBuffer(std::move(FileBufOrErr.get()));
}

std::unique_ptr<OutputFileMap> OutputFileMap::loadFromBuffer(StringRef Data) {
  std::unique_ptr<llvm::MemoryBuffer> Buffer{
    llvm::MemoryBuffer::getMemBuffer(Data)
  };
  return loadFromBuffer(std::move(Buffer));
}

std::unique_ptr<OutputFileMap>
OutputFileMap::loadFromBuffer(std::unique_ptr<llvm::MemoryBuffer> Buffer) {
  std::unique_ptr<OutputFileMap> OFM(new OutputFileMap());

  if (OFM->parse(std::move(Buffer)))
    return nullptr;

  return OFM;
}

const TypeToPathMap *OutputFileMap::getOutputMapForInput(StringRef Input) const{
  auto iter = InputToOutputsMap.find(Input);
  if (iter == InputToOutputsMap.end())
    return nullptr;
  else
    return &iter->second;
}

const TypeToPathMap *OutputFileMap::getOutputMapForSingleOutput() const {
  return getOutputMapForInput(StringRef());
}

void OutputFileMap::dump(llvm::raw_ostream &os, bool Sort) const {
  typedef std::pair<types::ID, std::string> TypePathPair;

  auto printOutputPair = [&os] (StringRef InputPath,
                                const TypePathPair &OutputPair) -> void {
    os << InputPath << " -> " << types::getTypeName(OutputPair.first) << ": \""
       << OutputPair.second << "\"\n";
  };

  if (Sort) {
    typedef std::pair<StringRef, TypeToPathMap> PathMapPair;
    std::vector<PathMapPair> Maps;
    for (auto &InputPair : InputToOutputsMap) {
      Maps.emplace_back(InputPair.first(), InputPair.second);
    }
    std::sort(Maps.begin(), Maps.end(), [] (const PathMapPair &LHS,
                                            const PathMapPair &RHS) -> bool {
      return LHS.first < RHS.first;
    });
    for (auto &InputPair : Maps) {
      const TypeToPathMap &Map = InputPair.second;
      std::vector<TypePathPair> Pairs;
      Pairs.insert(Pairs.end(), Map.begin(), Map.end());
      std::sort(Pairs.begin(), Pairs.end());
      for (auto &OutputPair : Pairs) {
        printOutputPair(InputPair.first, OutputPair);
      }
    }
  } else {
    for (auto &InputPair : InputToOutputsMap) {
      const TypeToPathMap &Map = InputPair.second;
      for (const TypePathPair &OutputPair : Map) {
        printOutputPair(InputPair.first(), OutputPair);
      }
    }
  }
}

bool OutputFileMap::parse(std::unique_ptr<llvm::MemoryBuffer> Buffer) {
  llvm::SourceMgr SM;
  llvm::yaml::Stream YAMLStream(Buffer->getMemBufferRef(), SM);
  auto I = YAMLStream.begin();
  if (I == YAMLStream.end())
    return true;

  auto Root = I->getRoot();
  if (!Root)
    return true;

  auto *Map = dyn_cast<llvm::yaml::MappingNode>(Root);
  if (!Map)
    return true;

  for (auto Pair : *Map) {
    llvm::yaml::Node *Key = Pair.getKey();
    llvm::yaml::Node *Value = Pair.getValue();

    if (!Key)
      return true;

    if (!Value)
      return true;

    auto *InputPath = dyn_cast<llvm::yaml::ScalarNode>(Key);
    if (!InputPath)
      return true;

    llvm::yaml::MappingNode *OutputMapNode =
      dyn_cast<llvm::yaml::MappingNode>(Value);
    if (!OutputMapNode)
      return true;

    TypeToPathMap OutputMap;

    for (auto OutputPair : *OutputMapNode) {
      llvm::yaml::Node *Key = OutputPair.getKey();
      llvm::yaml::Node *Value = OutputPair.getValue();

      auto *KindNode = dyn_cast<llvm::yaml::ScalarNode>(Key);
      if (!KindNode)
        return true;

      auto *Path = dyn_cast<llvm::yaml::ScalarNode>(Value);
      if (!Path)
        return true;

      llvm::SmallString<16> KindStorage;
      types::ID Kind =
        types::lookupTypeForName(KindNode->getValue(KindStorage));

      // Ignore unknown types, so that an older swiftc can be used with a newer
      // build system.
      if (Kind == types::TY_INVALID)
        continue;

      llvm::SmallString<128> PathStorage;
      OutputMap.insert(
        std::pair<types::ID, std::string>(Kind, Path->getValue(PathStorage)));
    }

    llvm::SmallString<128> InputStorage;
    InputToOutputsMap[InputPath->getValue(InputStorage)] = std::move(OutputMap);
  }

  return false;
}
