// 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 Conversion and its various subclasses.
#include <vector>

#include "fidl/new_syntax_converter.h"

namespace fidl::conv {

std::string TypeConversion::Write(fidl::utils::Syntax syntax) {
  std::string original = type_ctor_->copy_to_str();
  if (syntax == fidl::utils::Syntax::kOld) {
    return prefix() + original;
  }

  std::string out = prefix();
  std::vector<std::string> constraints;
  std::string id = type_ctor_->identifier->copy_to_str();

  // Nullability is the first constraint.
  if (type_ctor_->nullability == types::Nullability::kNullable) {
    // Special case: nullable types whose underlying type resolves to "struct"
    // need to be wrapped in "box<...>" instead of setting ":optional."
    if (underlying_type_.kind() == UnderlyingType::Kind::kStruct) {
      return prefix() + "box<" + id + ">";
    }
    constraints.emplace_back("optional");
  }

  // Certain wrapped types require special handling.
  if (!underlying_type_.is_behind_alias()) {
    if (underlying_type_.kind() == UnderlyingType::Kind::kArray) {
      // This type must be of the form "array<TYPE, SIZE>" and cannot have other
      // constraints, so return early.
      std::string size;
      if (type_ctor_->maybe_size != nullptr) {
        size = type_ctor_->maybe_size->copy_to_str();
      }
      return out + "array<" + wrapped_type_text_ + "," + size + ">";
    } else if (underlying_type_.kind() == UnderlyingType::Kind::kRequestHandle) {
      // Strip the prefix "client_end:" from the wrapped text, then use it as
      // a constraint on the server_end instead.
      //
      // This must be done because when converting a type like "request<P>" it
      // is always the case that P will be visited and converted first, and will
      // thus be passed to this converter as the wrapped_text "client_end:P," if
      // P is not an alias.  To make it into a valid server_end in the unaliased
      // case, we need to replace the "client_end" string with "server_end"
      // instead.
      std::string ptype = wrapped_type_text_;
      size_t colon_pos = ptype.find(':');
      if (colon_pos != std::string::npos) {
        // We want the string after the colon, so increment by one.
        colon_pos++;
        ptype = ptype.substr(colon_pos, ptype.length() - colon_pos);
      }
      constraints.emplace_back(ptype);
      id = "server_end";
    } else if (underlying_type_.kind() == UnderlyingType::Kind::kProtocol) {
      constraints.emplace_back(id);
      id = "client_end";
    } else if (underlying_type_.kind() == UnderlyingType::Kind::kVector) {
      if (wrapped_type_text_.empty()) {
        // Special case: bytes is a builtin alias for vector<uint8>.
        id = "bytes";
      } else {
        id = "vector<" + wrapped_type_text_ + ">";
      }
    }
  }
  out += id;

  // Process the remaining constraints in display order.
  if (type_ctor_->maybe_size != nullptr) {
    constraints.emplace_back(type_ctor_->maybe_size->copy_to_str());
  }
  if (type_ctor_->handle_subtype_identifier != nullptr) {
    constraints.emplace_back(type_ctor_->handle_subtype_identifier->copy_to_str());
  }
  if (type_ctor_->handle_rights != nullptr) {
    constraints.emplace_back(type_ctor_->handle_rights->copy_to_str());
  }

  // Build and append the constraints list.
  if (!constraints.empty() > 0) {
    std::string constraints_str = ":";
    if (constraints.size() == 1) {
      constraints_str += constraints[0];
    } else {
      bool first = true;
      for (const std::string& constraint : constraints) {
        if (first) {
          constraints_str += "<";
        } else {
          constraints_str += ",";
        }
        first = false;
        constraints_str += constraint;
      }
      constraints_str += ">";
    }
    out += constraints_str;
  }
  return out;
};

std::string UsingKeywordConversion::Write(fidl::utils::Syntax syntax) {
  std::string keyword = syntax == fidl::utils::Syntax::kOld ? "using " : "alias ";

  return prefix() + keyword + name_->copy_to_str() + " = " + type_text_;
};

std::string NameAndTypeConversion::Write(fidl::utils::Syntax syntax) {
  std::string ctor = !type_text_.empty() ? type_text_ : type_ctor_->copy_to_str();
  if (syntax == fidl::utils::Syntax::kOld) {
    return prefix() + ctor + " " + identifier_->copy_to_str();
  }

  return prefix() + identifier_->copy_to_str() + " " + ctor;
};

std::string MemberedDeclarationConversion::Write(fidl::utils::Syntax syntax) {
  std::string out;
  if (syntax == fidl::utils::Syntax::kOld) {
    out += prefix() + get_decl_str(syntax) + " " + identifier_->copy_to_str();
  } else {
    out += prefix() + "type " + identifier_->copy_to_str() + " = " + get_decl_str(syntax);
  }
  for (const std::string& member : members_) {
    out += member;
  }
  return out;
};

std::string BitsDeclarationConversion::Write(fidl::utils::Syntax syntax) {
  std::string out;
  Token name_token = identifier_->start_;
  const char* start_pos = name_token.span().data().data();
  const char* end_pos = name_token.span().data().data() + name_token.span().data().length();
  std::string name = std::string(start_pos, end_pos);

  if (syntax == fidl::utils::Syntax::kOld) {
    out += prefix() + get_decl_str(syntax) + " " + name + get_wrapped_type();
  } else {
    out += prefix() + "type " + name + " = " + get_decl_str(syntax) + get_wrapped_type();
  }
  for (const std::string& member : members_) {
    out += member;
  }
  return out;
};

}  // namespace fidl::conv
