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

#include <sstream>
#include <vector>

#include "cmCPackLog.h"
#include "cmList.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmValue.h"

cmCPackBundleGenerator::cmCPackBundleGenerator() = default;

cmCPackBundleGenerator::~cmCPackBundleGenerator() = default;

int cmCPackBundleGenerator::InitializeInternal()
{
  cmValue name = this->GetOption("CPACK_BUNDLE_NAME");
  if (!name) {
    cmCPackLogger(cmCPackLog::LOG_ERROR,
                  "CPACK_BUNDLE_NAME must be set to use the Bundle generator."
                    << std::endl);

    return 0;
  }

  if (this->GetOption("CPACK_BUNDLE_APPLE_CERT_APP")) {
    std::string const codesign_path = cmSystemTools::FindProgram("codesign");

    if (codesign_path.empty()) {
      cmCPackLogger(cmCPackLog::LOG_ERROR,
                    "Cannot locate codesign command" << std::endl);
      return 0;
    }
    this->SetOptionIfNotSet("CPACK_COMMAND_CODESIGN", codesign_path);
  }

  return this->Superclass::InitializeInternal();
}

char const* cmCPackBundleGenerator::GetPackagingInstallPrefix()
{
  this->InstallPrefix = cmStrCat('/', this->GetOption("CPACK_BUNDLE_NAME"),
                                 ".app/Contents/Resources");

  return this->InstallPrefix.c_str();
}

int cmCPackBundleGenerator::ConstructBundle()
{

  // Get required arguments ...
  cmValue cpack_bundle_name = this->GetOption("CPACK_BUNDLE_NAME");
  if (cpack_bundle_name->empty()) {
    cmCPackLogger(cmCPackLog::LOG_ERROR,
                  "CPACK_BUNDLE_NAME must be set." << std::endl);

    return 0;
  }

  cmValue cpack_bundle_plist = this->GetOption("CPACK_BUNDLE_PLIST");
  if (cpack_bundle_plist->empty()) {
    cmCPackLogger(cmCPackLog::LOG_ERROR,
                  "CPACK_BUNDLE_PLIST must be set." << std::endl);

    return 0;
  }

  cmValue cpack_bundle_icon = this->GetOption("CPACK_BUNDLE_ICON");
  if (cpack_bundle_icon->empty()) {
    cmCPackLogger(cmCPackLog::LOG_ERROR,
                  "CPACK_BUNDLE_ICON must be set." << std::endl);

    return 0;
  }

  // Get optional arguments ...
  cmValue cpack_bundle_startup_command =
    this->GetOption("CPACK_BUNDLE_STARTUP_COMMAND");

  // The staging directory contains everything that will end-up inside the
  // final disk image ...
  std::string const staging = toplevel;

  std::ostringstream contents;
  contents << staging << "/" << cpack_bundle_name
           << ".app/"
              "Contents";

  std::ostringstream application;
  application << contents.str()
              << "/"
                 "MacOS";

  std::ostringstream resources;
  resources << contents.str()
            << "/"
               "Resources";

  // Install a required, user-provided bundle metadata file ...
  std::ostringstream plist_source;
  plist_source << cpack_bundle_plist;

  std::ostringstream plist_target;
  plist_target << contents.str()
               << "/"
                  "Info.plist";

  if (!this->CopyFile(plist_source, plist_target)) {
    cmCPackLogger(
      cmCPackLog::LOG_ERROR,
      "Error copying plist.  Check the value of CPACK_BUNDLE_PLIST."
        << std::endl);

    return 0;
  }

  // Install a user-provided bundle icon ...
  std::ostringstream icon_source;
  icon_source << cpack_bundle_icon;

  std::ostringstream icon_target;
  icon_target << resources.str() << "/" << cpack_bundle_name << ".icns";

  if (!this->CopyFile(icon_source, icon_target)) {
    cmCPackLogger(
      cmCPackLog::LOG_ERROR,
      "Error copying bundle icon.  Check the value of CPACK_BUNDLE_ICON."
        << std::endl);

    return 0;
  }

  // Optionally a user-provided startup command (could be an
  // executable or a script) ...
  if (!cpack_bundle_startup_command->empty()) {
    std::ostringstream command_source;
    command_source << cpack_bundle_startup_command;

    std::ostringstream command_target;
    command_target << application.str() << "/" << cpack_bundle_name;

    if (!this->CopyFile(command_source, command_target)) {
      cmCPackLogger(cmCPackLog::LOG_ERROR,
                    "Error copying startup command. "
                    " Check the value of CPACK_BUNDLE_STARTUP_COMMAND."
                      << std::endl);

      return 0;
    }

    cmSystemTools::SetPermissions(command_target.str().c_str(), 0777);
  }

  return 1;
}

int cmCPackBundleGenerator::PackageFiles()
{
  if (!this->ConstructBundle()) {
    return 0;
  }

  if (!this->SignBundle(toplevel)) {
    return 0;
  }

  return this->CreateDMG(toplevel, packageFileNames[0]);
}

bool cmCPackBundleGenerator::SupportsComponentInstallation() const
{
  return false;
}

int cmCPackBundleGenerator::SignBundle(std::string const& src_dir)
{
  cmValue cpack_apple_cert_app =
    this->GetOption("CPACK_BUNDLE_APPLE_CERT_APP");

  // codesign the application.
  if (!cpack_apple_cert_app->empty()) {
    std::string output;
    std::string bundle_path;
    bundle_path =
      cmStrCat(src_dir, '/', this->GetOption("CPACK_BUNDLE_NAME"), ".app");

    // A list of additional files to sign, ie. frameworks and plugins.
    std::string const sign_parameter =
      this->GetOption("CPACK_BUNDLE_APPLE_CODESIGN_PARAMETER")
      ? *this->GetOption("CPACK_BUNDLE_APPLE_CODESIGN_PARAMETER")
      : "--deep -f";

    cmValue sign_files = this->GetOption("CPACK_BUNDLE_APPLE_CODESIGN_FILES");

    cmList relFiles{ sign_files };

    // sign the files supplied by the user, ie. frameworks.
    for (auto const& file : relFiles) {
      auto temp_sign_file_cmd =
        cmStrCat(this->GetOption("CPACK_COMMAND_CODESIGN"), ' ',
                 sign_parameter, " -s \"", cpack_apple_cert_app, "\" -i ",
                 this->GetOption("CPACK_APPLE_BUNDLE_ID"), " \"", bundle_path,
                 file, '"');

      if (!this->RunCommand(temp_sign_file_cmd, &output)) {
        cmCPackLogger(cmCPackLog::LOG_ERROR,
                      "Error signing file:" << bundle_path << file << std::endl
                                            << output << std::endl);

        return 0;
      }
    }

    // sign main binary
    auto temp_sign_binary_cmd =
      cmStrCat(this->GetOption("CPACK_COMMAND_CODESIGN"), ' ', sign_parameter,
               " -s \"", cpack_apple_cert_app, "\" \"", bundle_path, '"');

    if (!this->RunCommand(temp_sign_binary_cmd, &output)) {
      cmCPackLogger(cmCPackLog::LOG_ERROR,
                    "Error signing the application binary." << std::endl
                                                            << output
                                                            << std::endl);

      return 0;
    }

    // sign app bundle
    auto temp_codesign_cmd =
      cmStrCat(this->GetOption("CPACK_COMMAND_CODESIGN"), ' ', sign_parameter,
               " -s \"", cpack_apple_cert_app, '"');
    if (this->GetOption("CPACK_BUNDLE_APPLE_ENTITLEMENTS")) {
      temp_codesign_cmd +=
        cmStrCat(" --entitlements ",
                 this->GetOption("CPACK_BUNDLE_APPLE_ENTITLEMENTS"));
    }
    temp_codesign_cmd += cmStrCat(" \"", bundle_path, '"');

    if (!this->RunCommand(temp_codesign_cmd, &output)) {
      cmCPackLogger(cmCPackLog::LOG_ERROR,
                    "Error signing the application package." << std::endl
                                                             << output
                                                             << std::endl);

      return 0;
    }

    cmCPackLogger(cmCPackLog::LOG_OUTPUT,
                  "- Application has been codesigned" << std::endl);
    cmCPackLogger(cmCPackLog::LOG_VERBOSE,
                  (this->GetOption("CPACK_BUNDLE_APPLE_ENTITLEMENTS")
                     ? "with entitlement sandboxing"
                     : "without entitlement sandboxing")
                    << std::endl);
  }

  return 1;
}
