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

#include <cassert>

#include "cmGeneratorTarget.h"
#include "cmLocalGenerator.h"
#include "cmMakefile.h"
#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmTarget.h"
#include "cmValue.h"

class cmSourceFile;

cmOSXBundleGenerator::cmOSXBundleGenerator(cmGeneratorTarget* target)
  : GT(target)
  , Makefile(target->Target->GetMakefile())
  , LocalGenerator(target->GetLocalGenerator())
{
  if (this->MustSkip()) {
    return;
  }
}

bool cmOSXBundleGenerator::MustSkip()
{
  return !this->GT->HaveWellDefinedOutputFiles();
}

void cmOSXBundleGenerator::CreateAppBundle(std::string const& targetName,
                                           std::string& outpath,
                                           std::string const& config)
{
  if (this->MustSkip()) {
    return;
  }

  // Compute bundle directory names.
  std::string out = cmStrCat(
    outpath, '/',
    this->GT->GetAppBundleDirectory(config, cmGeneratorTarget::FullLevel));
  cmSystemTools::MakeDirectory(out);
  this->Makefile->AddCMakeOutputFile(out);

  // Configure the Info.plist file.  Note that it needs the executable name
  // to be set.
  std::string plist = cmStrCat(
    outpath, '/',
    this->GT->GetAppBundleDirectory(config, cmGeneratorTarget::ContentLevel),
    "/Info.plist");
  this->LocalGenerator->GenerateAppleInfoPList(this->GT, targetName, plist);
  this->Makefile->AddCMakeOutputFile(plist);
  outpath = out;
}

void cmOSXBundleGenerator::CreateFramework(
  std::string const& targetName, std::string const& outpath,
  std::string const& config, cmOSXBundleGenerator::SkipParts const& skipParts)
{
  if (this->MustSkip()) {
    return;
  }

  assert(this->MacContentFolders);

  // Compute the location of the top-level foo.framework directory.
  std::string contentdir = cmStrCat(
    outpath, '/',
    this->GT->GetFrameworkDirectory(config, cmGeneratorTarget::ContentLevel),
    '/');

  std::string newoutpath = outpath + "/" +
    this->GT->GetFrameworkDirectory(config, cmGeneratorTarget::FullLevel);

  std::string frameworkVersion = this->GT->GetFrameworkVersion();

  std::string name = cmSystemTools::GetFilenameName(targetName);
  if (!skipParts.InfoPlist) {
    // Configure the Info.plist file
    std::string plist = newoutpath;
    if (!this->Makefile->PlatformIsAppleEmbedded()) {
      // Put the Info.plist file into the Resources directory.
      this->MacContentFolders->insert("Resources");
      plist += "/Resources";
    }
    plist += "/Info.plist";
    this->LocalGenerator->GenerateFrameworkInfoPList(this->GT, name, plist);
  }

  // Generate Versions directory only for MacOSX frameworks
  if (this->Makefile->PlatformIsAppleEmbedded()) {
    return;
  }

  // TODO: Use the cmMakefileTargetGenerator::ExtraFiles vector to
  // drive rules to create these files at build time.
  std::string oldName;
  std::string newName;

  // Make foo.framework/Versions
  std::string versions = cmStrCat(contentdir, "Versions");
  cmSystemTools::MakeDirectory(versions);

  // Make foo.framework/Versions/version
  cmSystemTools::MakeDirectory(newoutpath);

  // Current -> version
  oldName = frameworkVersion;
  newName = cmStrCat(versions, "/Current");
  cmSystemTools::RemoveFile(newName);
  cmSystemTools::CreateSymlink(oldName, newName);
  this->Makefile->AddCMakeOutputFile(newName);

  // foo -> Versions/Current/foo
  oldName = cmStrCat("Versions/Current/", name);
  newName = cmStrCat(contentdir, name);
  cmSystemTools::RemoveFile(newName);
  cmSystemTools::CreateSymlink(oldName, newName);
  this->Makefile->AddCMakeOutputFile(newName);

  if (!skipParts.TextStubs) {
    // foo.tbd -> Versions/Current/foo.tbd
    cmValue tbdSuffix =
      this->Makefile->GetDefinition("CMAKE_APPLE_IMPORT_FILE_SUFFIX");
    oldName = cmStrCat("Versions/Current/", name, tbdSuffix);
    newName = cmStrCat(contentdir, name, tbdSuffix);
    cmSystemTools::RemoveFile(newName);
    cmSystemTools::CreateSymlink(oldName, newName);
    this->Makefile->AddCMakeOutputFile(newName);
  }

  // Resources -> Versions/Current/Resources
  if (this->MacContentFolders->find("Resources") !=
      this->MacContentFolders->end()) {
    oldName = "Versions/Current/Resources";
    newName = cmStrCat(contentdir, "Resources");
    cmSystemTools::RemoveFile(newName);
    cmSystemTools::CreateSymlink(oldName, newName);
    this->Makefile->AddCMakeOutputFile(newName);
  }

  // Headers -> Versions/Current/Headers
  if (this->MacContentFolders->find("Headers") !=
      this->MacContentFolders->end()) {
    oldName = "Versions/Current/Headers";
    newName = cmStrCat(contentdir, "Headers");
    cmSystemTools::RemoveFile(newName);
    cmSystemTools::CreateSymlink(oldName, newName);
    this->Makefile->AddCMakeOutputFile(newName);
  }

  // PrivateHeaders -> Versions/Current/PrivateHeaders
  if (this->MacContentFolders->find("PrivateHeaders") !=
      this->MacContentFolders->end()) {
    oldName = "Versions/Current/PrivateHeaders";
    newName = cmStrCat(contentdir, "PrivateHeaders");
    cmSystemTools::RemoveFile(newName);
    cmSystemTools::CreateSymlink(oldName, newName);
    this->Makefile->AddCMakeOutputFile(newName);
  }
}

void cmOSXBundleGenerator::CreateCFBundle(std::string const& targetName,
                                          std::string const& root,
                                          std::string const& config)
{
  if (this->MustSkip()) {
    return;
  }

  // Compute bundle directory names.
  std::string out = cmStrCat(
    root, '/',
    this->GT->GetCFBundleDirectory(config, cmGeneratorTarget::FullLevel));
  cmSystemTools::MakeDirectory(out);
  this->Makefile->AddCMakeOutputFile(out);

  // Configure the Info.plist file.  Note that it needs the executable name
  // to be set.
  std::string plist = cmStrCat(
    root, '/',
    this->GT->GetCFBundleDirectory(config, cmGeneratorTarget::ContentLevel),
    "/Info.plist");
  std::string name = cmSystemTools::GetFilenameName(targetName);
  this->LocalGenerator->GenerateAppleInfoPList(this->GT, name, plist);
  this->Makefile->AddCMakeOutputFile(plist);
}

void cmOSXBundleGenerator::GenerateMacOSXContentStatements(
  std::vector<cmSourceFile const*> const& sources,
  MacOSXContentGeneratorType* generator, std::string const& config)
{
  if (this->MustSkip()) {
    return;
  }

  for (cmSourceFile const* source : sources) {
    cmGeneratorTarget::SourceFileFlags tsFlags =
      this->GT->GetTargetSourceFileFlags(source);
    if (tsFlags.Type != cmGeneratorTarget::SourceFileTypeNormal) {
      (*generator)(*source, tsFlags.MacFolder, config);
    }
  }
}

std::string cmOSXBundleGenerator::InitMacOSXContentDirectory(
  char const* pkgloc, std::string const& config)
{
  // Construct the full path to the content subdirectory.

  std::string macdir = cmStrCat(this->GT->GetMacContentDirectory(
                                  config, cmStateEnums::RuntimeBinaryArtifact),
                                '/', pkgloc);
  cmSystemTools::MakeDirectory(macdir);

  // Record use of this content location.  Only the first level
  // directory is needed.
  {
    std::string loc = pkgloc;
    loc = loc.substr(0, loc.find('/'));
    this->MacContentFolders->insert(loc);
  }

  return macdir;
}
