// Copyright 2021 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// The implementation for the ConvertingTreeVisitor that re-prints a raw::File
// back into text format per some set of syntax rules.
#include "fidl/new_syntax_converter.h"

namespace fidl::conv {

// Until FTP-033 is fully implemented, it is possible for "strict" types to not
// have an actual "strict" keyword preceding them (ie, "strict union U {...}"
// and "union U {...}" are represented identically in the raw AST).  This
// helper function works around that problem by determining whether or not the
// actual "strict" keyword was used in the declaration text.
std::optional<types::Strictness> optional_strictness(types::Strictness strictness, bool specified) {
  if (!specified) {
    return std::nullopt;
  }
  return strictness;
}

// For types that only accept the strictness modifier (currently "bits" and
// "enum"), we don't store the presence of the modifier keyword as a bool.
// Instead, we just match the first token to its sub-kind to deduce whether or
// not the modifier keyword is used.
std::optional<types::Strictness> optional_strictness(Token& decl_start_token) {
  switch (decl_start_token.subkind()) {
    case Token::Subkind::kStrict:
      return types::Strictness::kStrict;
    case Token::Subkind::kFlexible:
      return types::Strictness::kFlexible;
    default:
      return std::nullopt;
  }
}

// Returns the "builtin" definition underpinning a type.  If named declaration
// is actually an alias, this method will recurse until all aliases are
// dereferenced and an actual, FIDL-native type can be deduced.
std::optional<UnderlyingType> resolve_as_user_defined_type(const flat::Name& name,
                                                           bool is_behind_alias) {
  const flat::Library* lib = name.library();
  const flat::Decl* decl_ptr = lib->LookupDeclByName(name);
  if (decl_ptr == nullptr) {
    return std::nullopt;
  }

  const flat::Decl::Kind& kind = decl_ptr->kind;
  if (kind != flat::Decl::Kind::kTypeAlias) {
    if (kind == flat::Decl::Kind::kResource) {
      // Special case: the only "resource_definition" in existence at the
      // moment is the one that defines "handle," so if we get to this point, we
      // should just assume the underlying type is a handle.
      return UnderlyingType(flat::Type::Kind::kHandle, is_behind_alias);
    }
    return UnderlyingType(decl_ptr->kind, is_behind_alias);
  }

  auto type_alias_ptr = static_cast<const flat::TypeAlias*>(decl_ptr);
  auto underlying_type =
      resolve_as_user_defined_type(type_alias_ptr->partial_type_ctor->name, true);
  if (underlying_type != std::nullopt) {
    return underlying_type;
  }
  return UnderlyingType(type_alias_ptr->partial_type_ctor->type->kind, true);
}

// Matches a string keyword to the "builtin" representing the FIDL-native type
// it represents.
std::optional<UnderlyingType> resolve_as_user_defined_type(const std::string& keyword) {
  const flat::Typespace root = flat::Typespace::RootTypes(nullptr);
  const flat::Name instrinsic = flat::Name::CreateIntrinsic(keyword);
  const flat::TypeTemplate* t = root.LookupTemplate(instrinsic);
  if (t == nullptr) {
    return std::nullopt;
  }

  if (keyword == "array") {
    return UnderlyingType(flat::Type::Kind::kArray, false);
  } else if (keyword == "vector") {
    return UnderlyingType(flat::Type::Kind::kVector, false);
  } else if (keyword == "bytes") {
    return UnderlyingType(flat::Type::Kind::kVector, false);
  } else if (keyword == "string") {
    return UnderlyingType(flat::Type::Kind::kString, false);
  } else if (keyword == "handle") {
    return UnderlyingType(flat::Type::Kind::kHandle, false);
  } else if (keyword == "request") {
    return UnderlyingType(flat::Type::Kind::kRequestHandle, false);
  } else {
    return UnderlyingType(flat::Type::Kind::kPrimitive, false);
  }
}

// Given a non-compound identifier, and a reference to the library in which
// that identifier is defined, we should be able to resolve the underlying
// built-in type underpinning that identifier.
std::optional<UnderlyingType> resolve_identifier(const std::unique_ptr<raw::Identifier>& identifier,
                                                 const flat::Library* lib) {
  std::string type_decl = identifier->copy_to_str();

  // Break up the type declaration - discard any "wrapped" types.
  size_t bracket_pos = type_decl.find_first_of('<');
  if (bracket_pos != std::string::npos) {
    type_decl = type_decl.substr(0, bracket_pos);
  };

  // We'll need to make a flat::Name from the type_decl string, which can then
  // be used to search the library for the name's definition recursively until
  // its underlying type can be deduced.
  auto underlying_type =
      resolve_as_user_defined_type(flat::Name::CreateSourced(lib, identifier->span()), false);
  if (underlying_type) {
    return underlying_type;
  }
  return resolve_as_user_defined_type(type_decl);
}

// Lookup the definition of a type's "key" identifier (ie, "vector" in the
// identifier "vector<array<uint8>:>" or "Foo" in "some.lib.Foo") in a given
// library.
std::optional<UnderlyingType> resolve_type(
    const std::unique_ptr<raw::TypeConstructorOld>& type_ctor, const flat::Library* lib) {
  std::unique_ptr<raw::CompoundIdentifier>& id = type_ctor->identifier;
  std::string type_decl = id->copy_to_str();

  // If there is at least one period in the declaration identifier, there is a
  // possibility that this is a reference to an imported library.  To verify
  // this, we'll construct the library name (ex, "some.library.Foo" becomes
  // just "some.library") and see if we can find it in the final library's
  // dependent libraries.
  size_t last_dot_pos = type_decl.find_last_of('.');
  if (last_dot_pos != std::string::npos) {
    flat::Library* dep_lib = nullptr;
    std::vector<std::string_view> lib_name;
    for (size_t i = 0; i < id->components.size() - 1; i++) {
      lib_name.emplace_back(id->components[i]->span().data());
    }

    const flat::Libraries* libs = lib->GetLibraries();
    if (libs->Lookup(lib_name, &dep_lib)) {
      return resolve_identifier(id->components.back(), dep_lib);
    }
  };

  // Looks like this was not a reference to a definition in an imported
  // library after all.  Go ahead and look for it in our current library.
  return resolve_identifier(id->components.back(), lib);
}

std::optional<UnderlyingType> ConvertingTreeVisitor::resolve(
    const std::unique_ptr<raw::TypeConstructorOld>& type_ctor) {
  return resolve_type(type_ctor, library_);
}

void ConvertingTreeVisitor::OnBitsDeclaration(
    const std::unique_ptr<raw::BitsDeclaration>& element) {
  Token& end = element->identifier->end_;
  if (element->maybe_type_ctor != nullptr) {
    end = element->maybe_type_ctor->end_;
  }

  auto ref =
      element->maybe_type_ctor == nullptr
          ? std::nullopt
          : std::make_optional<std::reference_wrapper<std::unique_ptr<raw::TypeConstructorOld>>>(
                element->maybe_type_ctor);
  std::unique_ptr<Conversion> conv = std::make_unique<BitsDeclarationConversion>(
      element->identifier, ref, optional_strictness(*element->decl_start_token));
  Converting converting(this, std::move(conv), *element->decl_start_token, end);
  TreeVisitor::OnBitsDeclaration(element);
}

void ConvertingTreeVisitor::OnConstDeclaration(
    const std::unique_ptr<raw::ConstDeclaration>& element) {
  const auto& type_ctor = std::get<std::unique_ptr<raw::TypeConstructorOld>>(element->type_ctor);
  std::unique_ptr<Conversion> conv =
      std::make_unique<NameAndTypeConversion>(element->identifier, type_ctor);
  Converting converting(this, std::move(conv), type_ctor->start_, element->identifier->end_);
  TreeVisitor::OnConstDeclaration(element);
}

void ConvertingTreeVisitor::OnEnumDeclaration(
    const std::unique_ptr<raw::EnumDeclaration>& element) {
  Token& end = element->identifier->end_;
  if (element->maybe_type_ctor != nullptr) {
    end = element->maybe_type_ctor->end_;
  }

  auto ref =
      element->maybe_type_ctor == nullptr
          ? std::nullopt
          : std::make_optional<std::reference_wrapper<std::unique_ptr<raw::TypeConstructorOld>>>(
                element->maybe_type_ctor);
  std::unique_ptr<Conversion> conv = std::make_unique<EnumDeclarationConversion>(
      element->identifier, ref, optional_strictness(*element->decl_start_token));
  Converting converting(this, std::move(conv), *element->decl_start_token, end);
  TreeVisitor::OnEnumDeclaration(element);
}

void ConvertingTreeVisitor::OnFile(std::unique_ptr<fidl::raw::File> const& element) {
  last_conversion_end_ = element->start_.previous_end().data().data();
  comments_ = std::move(element->comment_tokens_list);
  DeclarationOrderTreeVisitor::OnFile(element);
  converted_output_ += last_conversion_end_;
}

void ConvertingTreeVisitor::OnParameter(const std::unique_ptr<raw::Parameter>& element) {
  const auto& type_ctor = std::get<std::unique_ptr<raw::TypeConstructorOld>>(element->type_ctor);
  std::unique_ptr<Conversion> conv =
      std::make_unique<NameAndTypeConversion>(element->identifier, type_ctor);
  Converting converting(this, std::move(conv), type_ctor->start_, element->identifier->end_);
  TreeVisitor::OnParameter(element);
}

void ConvertingTreeVisitor::OnStructDeclaration(
    const std::unique_ptr<raw::StructDeclaration>& element) {
  std::unique_ptr<Conversion> conv =
      std::make_unique<StructDeclarationConversion>(element->identifier, element->resourceness);
  Converting converting(this, std::move(conv), *element->decl_start_token,
                        element->identifier->end_);
  TreeVisitor::OnStructDeclaration(element);
}

void ConvertingTreeVisitor::OnResourceProperty(
    const std::unique_ptr<raw::ResourceProperty>& element) {
  const auto& type_ctor = std::get<std::unique_ptr<raw::TypeConstructorOld>>(element->type_ctor);
  std::unique_ptr<Conversion> conv =
      std::make_unique<NameAndTypeConversion>(element->identifier, type_ctor);
  Converting converting(this, std::move(conv), type_ctor->start_, element->identifier->end_);
  TreeVisitor::OnResourceProperty(element);
}

void ConvertingTreeVisitor::OnStructMember(const std::unique_ptr<raw::StructMember>& element) {
  std::unique_ptr<Conversion> conv =
      std::make_unique<NameAndTypeConversion>(element->identifier, element->type_ctor);
  Converting converting(this, std::move(conv), element->type_ctor->start_,
                        element->identifier->end_);
  TreeVisitor::OnStructMember(element);
}

void ConvertingTreeVisitor::OnTableDeclaration(
    const std::unique_ptr<raw::TableDeclaration>& element) {
  std::unique_ptr<Conversion> conv =
      std::make_unique<TableDeclarationConversion>(element->identifier, element->resourceness);
  Converting converting(this, std::move(conv), *element->decl_start_token,
                        element->identifier->end_);
  TreeVisitor::OnTableDeclaration(element);
}

void ConvertingTreeVisitor::OnTableMember(const std::unique_ptr<raw::TableMember>& element) {
  if (element->maybe_used != nullptr) {
    std::unique_ptr<Conversion> conv = std::make_unique<NameAndTypeConversion>(
        element->maybe_used->identifier, element->maybe_used->type_ctor);
    Converting converting(this, std::move(conv), element->maybe_used->type_ctor->start_,
                          element->maybe_used->identifier->end_);
    TreeVisitor::OnTableMember(element);
  } else {
    TreeVisitor::OnTableMember(element);
  }
}

void ConvertingTreeVisitor::OnTypeConstructorOld(
    const std::unique_ptr<raw::TypeConstructorOld>& element) {
  std::optional<UnderlyingType> underlying_type = resolve(element);

  // We should never get a null Builtin - if we do, there is a mistake in the
  // converter code.  Failing this assert means we are looking at an
  // identifier that is neither explicitly defined in the source, nor
  // intrinsic to the language.  If that's the case, where did it come from?
  assert(underlying_type.has_value() && "must resolve underlying builtin value for type");

  std::unique_ptr<Conversion> conv =
      std::make_unique<TypeConversion>(element, underlying_type.value());
  Converting converting(this, std::move(conv), element->start_, element->end_);
  TreeVisitor::OnTypeConstructorOld(element);
}

void ConvertingTreeVisitor::OnUnionDeclaration(
    const std::unique_ptr<raw::UnionDeclaration>& element) {
  std::unique_ptr<Conversion> conv = std::make_unique<UnionDeclarationConversion>(
      element->identifier, optional_strictness(element->strictness, element->strictness_specified),
      element->resourceness);
  Converting converting(this, std::move(conv), *element->decl_start_token,
                        element->identifier->end_);
  TreeVisitor::OnUnionDeclaration(element);
}

void ConvertingTreeVisitor::OnUnionMember(const std::unique_ptr<raw::UnionMember>& element) {
  if (element->maybe_used != nullptr) {
    std::unique_ptr<Conversion> conv = std::make_unique<NameAndTypeConversion>(
        element->maybe_used->identifier, element->maybe_used->type_ctor);
    Converting converting(this, std::move(conv), element->maybe_used->type_ctor->start_,
                          element->maybe_used->identifier->end_);
    TreeVisitor::OnUnionMember(element);
  } else {
    TreeVisitor::OnUnionMember(element);
  }
}

void ConvertingTreeVisitor::OnUsing(const std::unique_ptr<raw::Using>& element) {
  if (element->maybe_type_ctor != nullptr) {
    std::unique_ptr<Conversion> conv =
        std::make_unique<UsingKeywordConversion>(element->using_path, element->maybe_type_ctor);
    Converting converting(this, std::move(conv), *element->decl_start_token,
                          element->maybe_type_ctor->end_);
  }
  TreeVisitor::OnUsing(element);
}

Converting::Converting(ConvertingTreeVisitor* ctv, std::unique_ptr<Conversion> conversion,
                       const Token& start, const Token& end)
    : ctv_(ctv) {
  const char* copy_from = ctv_->last_conversion_end_;
  const char* copy_until = start.data().data();
  const char* conversion_end = end.data().data() + end.data().length();

  if (conversion_end > ctv_->last_conversion_end_) {
    // We should only enter this block if we are in a nested conversion.
    ctv_->last_conversion_end_ = conversion_end;
  }
  if (copy_from < copy_until) {
    auto cr = std::make_unique<CopyRange>(copy_from, copy_until);
    conversion->AddPrefix(std::move(cr));
  }

  // Any stray comments contained inside the span being converted should be
  // added to the prefix as well.
  while (ctv->last_comment_ < ctv->comments_.size()) {
    std::string_view comment = ctv->comments_[ctv->last_comment_]->span().data();

    // Make sure not to consume comments past the end of the current conversion
    // span.
    if (comment.data() > ctv_->last_conversion_end_) {
      break;
    }

    if (comment.data() > start.data().data()) {
      const char* from = comment.data();
      const char* until = from + comment.length() + 1;
      auto cr = std::make_unique<CopyRange>(from, until);
      conversion->AddPrefix(std::move(cr));
    }
    ctv->last_comment_++;
  }

  ctv_->open_conversions_.push(std::move(conversion));
}

Converting::~Converting() {
  std::unique_ptr<Conversion> conv = std::move(ctv_->open_conversions_.top());
  ctv_->open_conversions_.pop();
  std::string text = conv->Write(ctv_->to_syntax_);
  if (!ctv_->open_conversions_.empty()) {
    ctv_->open_conversions_.top()->AddChildText(text);
  } else {
    ctv_->converted_output_ += text;
  }
}

}  // namespace fidl::conv
