/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
   file LICENSE.rst or https://cmake.org/licensing for details.  */
#include "cmXCodeObject.h"

#include <ostream>

#include <cm/string_view>
#include <cmext/string_view>

char const* cmXCodeObject::PBXTypeNames[] = {
  /* clang-format needs this comment to break after the opening brace */
  "PBXGroup",
  "PBXBuildStyle",
  "PBXProject",
  "PBXHeadersBuildPhase",
  "PBXSourcesBuildPhase",
  "PBXFrameworksBuildPhase",
  "PBXNativeTarget",
  "PBXFileReference",
  "PBXBuildFile",
  "PBXContainerItemProxy",
  "PBXTargetDependency",
  "PBXShellScriptBuildPhase",
  "PBXResourcesBuildPhase",
  "PBXApplicationReference",
  "PBXExecutableFileReference",
  "PBXLibraryReference",
  "PBXToolTarget",
  "PBXLibraryTarget",
  "PBXAggregateTarget",
  "XCBuildConfiguration",
  "XCConfigurationList",
  "PBXCopyFilesBuildPhase",
  "None"
};

cmXCodeObject::~cmXCodeObject()
{
  this->Version = 15;
}

cmXCodeObject::cmXCodeObject(PBXType ptype, Type type, std::string id)
{
  this->Version = 15;
  this->Target = nullptr;
  this->Object = nullptr;

  this->IsA = ptype;

  this->Id = std::move(id);

  this->TypeValue = type;
  if (this->TypeValue == OBJECT) {
    this->AddAttribute("isa", nullptr);
  }
}

bool cmXCodeObject::IsEmpty() const
{
  switch (this->TypeValue) {
    case OBJECT_LIST:
      return this->List.empty();
    case STRING:
      return this->String.empty();
    case ATTRIBUTE_GROUP:
      return this->ObjectAttributes.empty();
    case OBJECT_REF:
    case OBJECT:
      return this->Object == nullptr;
  }
  return true; // unreachable, but quiets warnings
}

void cmXCodeObject::Indent(int level, std::ostream& out)
{
  while (level) {
    out << "\t";
    level--;
  }
}

void cmXCodeObject::Print(std::ostream& out)
{
  std::string separator = "\n";
  int indentFactor = 1;
  cmXCodeObject::Indent(2 * indentFactor, out);
  if (this->Version > 15 &&
      (this->IsA == PBXFileReference || this->IsA == PBXBuildFile)) {
    separator = " ";
    indentFactor = 0;
  }
  out << this->Id;
  this->PrintComment(out);
  out << " = {";
  if (separator == "\n"_s) {
    out << separator;
  }
  cmXCodeObject::Indent(3 * indentFactor, out);
  out << "isa = " << PBXTypeNames[this->IsA] << ";" << separator;
  for (auto const& keyVal : this->ObjectAttributes) {
    if (keyVal.first == "isa"_s) {
      continue;
    }

    PrintAttribute(out, 3, separator, indentFactor, keyVal.first,
                   keyVal.second, this);
  }
  cmXCodeObject::Indent(2 * indentFactor, out);
  out << "};\n";
}

void cmXCodeObject::PrintAttribute(std::ostream& out, int level,
                                   std::string const& separator, int factor,
                                   std::string const& name,
                                   cmXCodeObject const* object,
                                   cmXCodeObject const* parent)
{
  cmXCodeObject::Indent(level * factor, out);
  switch (object->TypeValue) {
    case OBJECT_LIST: {
      out << name << " = (";
      if (parent->TypeValue != ATTRIBUTE_GROUP) {
        out << separator;
      }
      for (unsigned int i = 0; i < object->List.size(); ++i) {
        if (object->List[i]->TypeValue == STRING) {
          object->List[i]->PrintString(out);
          if (i + 1 < object->List.size()) {
            out << ",";
          }
        } else {
          cmXCodeObject::Indent((level + 1) * factor, out);
          out << object->List[i]->Id;
          object->List[i]->PrintComment(out);
          out << "," << separator;
        }
      }
      if (parent->TypeValue != ATTRIBUTE_GROUP) {
        cmXCodeObject::Indent(level * factor, out);
      }
      out << ");" << separator;
    } break;

    case ATTRIBUTE_GROUP: {
      out << name << " = {";
      if (separator == "\n"_s) {
        out << separator;
      }
      for (auto const& keyVal : object->ObjectAttributes) {
        PrintAttribute(out, (level + 1) * factor, separator, factor,
                       keyVal.first, keyVal.second, object);
      }
      cmXCodeObject::Indent(level * factor, out);
      out << "};" << separator;
    } break;

    case OBJECT_REF: {
      cmXCodeObject::PrintString(out, name);
      out << " = " << object->Object->Id;
      if (object->Object->HasComment() && name != "remoteGlobalIDString"_s) {
        object->Object->PrintComment(out);
      }
      out << ";" << separator;
    } break;

    case STRING: {
      cmXCodeObject::PrintString(out, name);
      out << " = ";
      object->PrintString(out);
      out << ";" << separator;
    } break;

    default: {
      break;
    }
  }
}

void cmXCodeObject::PrintList(std::vector<cmXCodeObject*> const& objs,
                              std::ostream& out)
{
  cmXCodeObject::Indent(1, out);
  out << "objects = {\n";
  for (auto* obj : objs) {
    if (obj->TypeValue == OBJECT) {
      obj->Print(out);
    }
  }
  cmXCodeObject::Indent(1, out);
  out << "};\n";
}

void cmXCodeObject::CopyAttributes(cmXCodeObject* copy)
{
  this->ObjectAttributes = copy->ObjectAttributes;
  this->List = copy->List;
  this->String = copy->String;
  this->Object = copy->Object;
}

void cmXCodeObject::PrintString(std::ostream& os, std::string const& String)
{
  // The string needs to be quoted if it contains any characters
  // considered special by the Xcode project file parser.
  bool needQuote = (String.empty() || String.find("//") != std::string::npos ||
                    String.find_first_not_of("ABCDEFGHIJKLMNOPQRSTUVWXYZ"
                                             "abcdefghijklmnopqrstuvwxyz"
                                             "0123456789"
                                             "$_./") != std::string::npos);
  char const* quote = needQuote ? "\"" : "";

  // Print the string, quoted and escaped as necessary.
  os << quote;
  for (auto c : String) {
    if (c == '"' || c == '\\') {
      // Escape double-quotes and backslashes.
      os << '\\';
    }
    os << c;
  }
  os << quote;
}

void cmXCodeObject::PrintString(std::ostream& os) const
{
  cmXCodeObject::PrintString(os, this->String);
}

void cmXCodeObject::SetString(cm::string_view s)
{
  this->String = std::string(s);
}
