/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
   file Copyright.txt 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")) {
    const std::string codesign_path = cmSystemTools::FindProgram(
      "codesign", std::vector<std::string>(), false);

    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();
}

const char* 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(const std::string& 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.
    const std::string 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;
}
