/*! Loads the project specified in \b projectPath.\n
        \b projectPath must be an absolute path.
*/
void TProject::load(const TFilePath &projectPath) {
  assert(isAProjectPath(projectPath));

  TFilePath latestProjectPath = getLatestVersionProjectPath(projectPath);
  TFilePath inputProjectPath  = searchProjectPath(projectPath.getParentDir());

  TProjectManager *pm = TProjectManager::instance();
  m_name              = pm->projectPathToProjectName(latestProjectPath);
  m_path              = latestProjectPath;

  m_folderNames.clear();
  m_folders.clear();
  m_useScenePathFlags.clear();
  delete m_sprop;
  m_sprop = new TSceneProperties();

  // Read the project
  TIStream is(inputProjectPath);
  if (!is) return;

  string tagName;
  if (!is.matchTag(tagName) || tagName != "project") return;

  while (is.matchTag(tagName)) {
    if (tagName == "folders") {
      while (is.matchTag(tagName)) {
        if (tagName == "folder") {
          string name = is.getTagAttribute("name");
          TFilePath path(is.getTagAttribute("path"));
          setFolder(name, path);
          string useScenePath = is.getTagAttribute("useScenePath");
          setUseScenePath(name, useScenePath == "yes");
        } else
          throw TException("expected <folder>");
      }
      is.matchEndTag();
    } else if (tagName == "version") {
      int major, minor;
      is >> major >> minor;
      is.setVersion(VersionNumber(major, minor));
      is.matchEndTag();
    } else if (tagName == "sceneProperties") {
/*! Saves the project in the specified path.
        The TfilePath fp must be an absolute path. The project is saved as a xml
   file.\n
        Uses TProjectManager and TOStream.
        \note Exceptions can be thrown.
        \see TProjectManager and TOStream.
*/
bool TProject::save(const TFilePath &projectPath) {
  assert(isAProjectPath(projectPath));

  TProjectManager *pm     = TProjectManager::instance();
  m_name                  = pm->projectPathToProjectName(projectPath);
  m_path                  = getLatestVersionProjectPath(projectPath);
  TFilePath projectFolder = projectPath.getParentDir();

  if (!TFileStatus(projectFolder).doesExist()) {
    try {
      TSystem::mkDir(projectFolder);
    } catch (...) {
      return false;
    }
  }

  TFilePath sceneFolder    = decode(getFolder(TProject::Scenes));
  TFilePath scenesDescPath = sceneFolder + "scenes.xml";

  TFileStatus fs(projectPath);
  if (fs.doesExist() && !fs.isWritable()) {
    throw TSystemException(
        projectPath,
        "Cannot save the project settings. The file is read-only.");
    return false;
  }
  TFileStatus fs2(scenesDescPath);
  if (fs2.doesExist() && !fs2.isWritable()) {
    throw TSystemException(
        projectPath,
        "Cannot save the project settings. The scenes file is read-only.");
    return false;
  }

  TOStream os(m_path);
  os.openChild("project");
  os.openChild("version");
  os << 70 << 1;    // Standard version signature:
  os.closeChild();  //   <Major Toonz version number * 10>.<Major version
                    //   advancement>
  os.openChild("folders");
  int i = 0;
  for (i = 0; i < getFolderCount(); i++) {
    TFilePath folderRelativePath = getFolder(i);
    if (folderRelativePath == TFilePath()) continue;
    std::map<std::string, string> attr;
    string folderName = getFolderName(i);
    attr["name"]      = folderName;
    attr["path"]      = ::to_string(folderRelativePath);  // escape()
    if (getUseScenePath(folderName)) attr["useScenePath"] = "yes";
    os.openCloseChild("folder", attr);
  }
  os.closeChild();

  os.openChild("sceneProperties");
  getSceneProperties().saveData(os);
  os.closeChild();
  os.closeChild();

  // crea (se necessario) le directory relative ai vari folder
  for (i = 0; i < getFolderCount(); i++)
    if (isConstantFolder(i)) {
      TFilePath fp = getFolder(i);
      if (fp == TFilePath()) continue;
      fp = decode(fp);
      // if(!fp.isAbsolute()) fp = projectFolder + fp;
      if (!TFileStatus(fp).doesExist()) {
        try {
          TSystem::mkDir(fp);
        } catch (...) {
        }
      }
    }

  /*-- +scenes だけでなく、全てのProject Folderにscenes.xmlを生成する --*/
  std::vector<std::string> foldernames;
  pm->getFolderNames(foldernames);
  for (int f = 0; f < foldernames.size(); f++) {
    TFilePath folderpath = decode(getFolder(foldernames.at(f)));
    if (folderpath.isEmpty() || !isConstantFolder(f)) continue;

    TFilePath xmlPath = folderpath + "scenes.xml";
    TFileStatus xmlfs(xmlPath);
    if (xmlfs.doesExist() && !xmlfs.isWritable()) continue;

    TFilePath relativeProjectFolder =
        makeRelative(folderpath, m_path.getParentDir());

    TOStream os2(xmlPath);
    std::map<std::string, string> attr;
    attr["type"] = "projectFolder";
    os2.openChild("parentProject", attr);
    os2 << relativeProjectFolder;
    os2.closeChild();
  }

  // The project has been successfully saved. In case there are other
  // project files from older Toonz project versions, those files are
  // renamed so that older Toonz versions can no longer 'see' it.
  if (!isFolderUnderVersionControl(projectFolder))
    hideOlderProjectFiles(projectFolder);

  return true;
}