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

#include <cmConfigure.h>
#include <sstream>
#include <stddef.h>
#include <utility>

#include "CPack/cmCPackGenerator.h"
#include "CPack/cmCPackLog.h"
#include "cmCPackIFWGenerator.h"
#include "cmCPackIFWPackage.h"
#include "cmCPackIFWRepository.h"
#include "cmGeneratedFileStream.h"
#include "cmSystemTools.h"
#include "cmXMLParser.h"
#include "cmXMLWriter.h"

#ifdef cmCPackLogger
#undef cmCPackLogger
#endif
#define cmCPackLogger(logType, msg)                                           \
  do {                                                                        \
    std::ostringstream cmCPackLog_msg;                                        \
    cmCPackLog_msg << msg;                                                    \
    if (Generator) {                                                          \
      Generator->Logger->Log(logType, __FILE__, __LINE__,                     \
                             cmCPackLog_msg.str().c_str());                   \
    }                                                                         \
  } while (false)

cmCPackIFWInstaller::cmCPackIFWInstaller()
  : Generator(CM_NULLPTR)
{
}

const char* cmCPackIFWInstaller::GetOption(const std::string& op) const
{
  return Generator ? Generator->GetOption(op) : CM_NULLPTR;
}

bool cmCPackIFWInstaller::IsOn(const std::string& op) const
{
  return Generator ? Generator->IsOn(op) : false;
}

bool cmCPackIFWInstaller::IsVersionLess(const char* version)
{
  return Generator ? Generator->IsVersionLess(version) : false;
}

bool cmCPackIFWInstaller::IsVersionGreater(const char* version)
{
  return Generator ? Generator->IsVersionGreater(version) : false;
}

bool cmCPackIFWInstaller::IsVersionEqual(const char* version)
{
  return Generator ? Generator->IsVersionEqual(version) : false;
}

void cmCPackIFWInstaller::ConfigureFromOptions()
{
  // Name;
  if (const char* optIFW_PACKAGE_NAME =
        this->GetOption("CPACK_IFW_PACKAGE_NAME")) {
    Name = optIFW_PACKAGE_NAME;
  } else if (const char* optPACKAGE_NAME =
               this->GetOption("CPACK_PACKAGE_NAME")) {
    Name = optPACKAGE_NAME;
  } else {
    Name = "Your package";
  }

  // Title;
  if (const char* optIFW_PACKAGE_TITLE =
        GetOption("CPACK_IFW_PACKAGE_TITLE")) {
    Title = optIFW_PACKAGE_TITLE;
  } else if (const char* optPACKAGE_DESCRIPTION_SUMMARY =
               GetOption("CPACK_PACKAGE_DESCRIPTION_SUMMARY")) {
    Title = optPACKAGE_DESCRIPTION_SUMMARY;
  } else {
    Title = "Your package description";
  }

  // Version;
  if (const char* option = GetOption("CPACK_PACKAGE_VERSION")) {
    Version = option;
  } else {
    Version = "1.0.0";
  }

  // Publisher
  if (const char* optIFW_PACKAGE_PUBLISHER =
        GetOption("CPACK_IFW_PACKAGE_PUBLISHER")) {
    Publisher = optIFW_PACKAGE_PUBLISHER;
  } else if (const char* optPACKAGE_VENDOR =
               GetOption("CPACK_PACKAGE_VENDOR")) {
    Publisher = optPACKAGE_VENDOR;
  }

  // ProductUrl
  if (const char* option = GetOption("CPACK_IFW_PRODUCT_URL")) {
    ProductUrl = option;
  }

  // ApplicationIcon
  if (const char* option = GetOption("CPACK_IFW_PACKAGE_ICON")) {
    if (cmSystemTools::FileExists(option)) {
      InstallerApplicationIcon = option;
    } else {
      // TODO: implement warning
    }
  }

  // WindowIcon
  if (const char* option = GetOption("CPACK_IFW_PACKAGE_WINDOW_ICON")) {
    if (cmSystemTools::FileExists(option)) {
      InstallerWindowIcon = option;
    } else {
      // TODO: implement warning
    }
  }

  // Logo
  if (const char* option = GetOption("CPACK_IFW_PACKAGE_LOGO")) {
    if (cmSystemTools::FileExists(option)) {
      Logo = option;
    } else {
      // TODO: implement warning
    }
  }

  // Start menu
  if (const char* optIFW_START_MENU_DIR =
        this->GetOption("CPACK_IFW_PACKAGE_START_MENU_DIRECTORY")) {
    StartMenuDir = optIFW_START_MENU_DIR;
  } else {
    StartMenuDir = Name;
  }

  // Default target directory for installation
  if (const char* optIFW_TARGET_DIRECTORY =
        GetOption("CPACK_IFW_TARGET_DIRECTORY")) {
    TargetDir = optIFW_TARGET_DIRECTORY;
  } else if (const char* optPACKAGE_INSTALL_DIRECTORY =
               GetOption("CPACK_PACKAGE_INSTALL_DIRECTORY")) {
    TargetDir = "@ApplicationsDir@/";
    TargetDir += optPACKAGE_INSTALL_DIRECTORY;
  } else {
    TargetDir = "@RootDir@/usr/local";
  }

  // Default target directory for installation with administrator rights
  if (const char* option = GetOption("CPACK_IFW_ADMIN_TARGET_DIRECTORY")) {
    AdminTargetDir = option;
  }

  // Maintenance tool
  if (const char* optIFW_MAINTENANCE_TOOL =
        this->GetOption("CPACK_IFW_PACKAGE_MAINTENANCE_TOOL_NAME")) {
    MaintenanceToolName = optIFW_MAINTENANCE_TOOL;
  }

  // Maintenance tool ini file
  if (const char* optIFW_MAINTENANCE_TOOL_INI =
        this->GetOption("CPACK_IFW_PACKAGE_MAINTENANCE_TOOL_INI_FILE")) {
    MaintenanceToolIniFile = optIFW_MAINTENANCE_TOOL_INI;
  }

  // Allow non-ASCII characters
  if (this->GetOption("CPACK_IFW_PACKAGE_ALLOW_NON_ASCII_CHARACTERS")) {
    if (IsOn("CPACK_IFW_PACKAGE_ALLOW_NON_ASCII_CHARACTERS")) {
      AllowNonAsciiCharacters = "true";
    } else {
      AllowNonAsciiCharacters = "false";
    }
  }

  // Space in path
  if (this->GetOption("CPACK_IFW_PACKAGE_ALLOW_SPACE_IN_PATH")) {
    if (IsOn("CPACK_IFW_PACKAGE_ALLOW_SPACE_IN_PATH")) {
      AllowSpaceInPath = "true";
    } else {
      AllowSpaceInPath = "false";
    }
  }

  // Control script
  if (const char* optIFW_CONTROL_SCRIPT =
        this->GetOption("CPACK_IFW_PACKAGE_CONTROL_SCRIPT")) {
    ControlScript = optIFW_CONTROL_SCRIPT;
  }

  // Resources
  if (const char* optIFW_PACKAGE_RESOURCES =
        this->GetOption("CPACK_IFW_PACKAGE_RESOURCES")) {
    Resources.clear();
    cmSystemTools::ExpandListArgument(optIFW_PACKAGE_RESOURCES, Resources);
  }
}

/** \class cmCPackIFWResourcesParser
 * \brief Helper class that parse resources form .qrc (Qt)
 */
class cmCPackIFWResourcesParser : public cmXMLParser
{
public:
  cmCPackIFWResourcesParser(cmCPackIFWInstaller* i)
    : installer(i)
    , file(false)
  {
    path = i->Directory + "/resources";
  }

  bool ParseResource(size_t r)
  {
    hasFiles = false;
    hasErrors = false;

    basePath = cmSystemTools::GetFilenamePath(installer->Resources[r].data());

    ParseFile(installer->Resources[r].data());

    return hasFiles && !hasErrors;
  }

  cmCPackIFWInstaller* installer;
  bool file, hasFiles, hasErrors;
  std::string path, basePath;

protected:
  void StartElement(const std::string& name, const char** /*atts*/) CM_OVERRIDE
  {
    file = name == "file";
    if (file) {
      hasFiles = true;
    }
  }

  void CharacterDataHandler(const char* data, int length) CM_OVERRIDE
  {
    if (file) {
      std::string content(data, data + length);
      content = cmSystemTools::TrimWhitespace(content);
      std::string source = basePath + "/" + content;
      std::string destination = path + "/" + content;
      if (!cmSystemTools::CopyFileIfDifferent(source.data(),
                                              destination.data())) {
        hasErrors = true;
      }
    }
  }

  void EndElement(const std::string& /*name*/) CM_OVERRIDE {}
};

void cmCPackIFWInstaller::GenerateInstallerFile()
{
  // Lazy directory initialization
  if (Directory.empty() && Generator) {
    Directory = Generator->toplevel;
  }

  // Output stream
  cmGeneratedFileStream fout((Directory + "/config/config.xml").data());
  cmXMLWriter xout(fout);

  xout.StartDocument();

  WriteGeneratedByToStrim(xout);

  xout.StartElement("Installer");

  xout.Element("Name", Name);
  xout.Element("Version", Version);
  xout.Element("Title", Title);

  if (!Publisher.empty()) {
    xout.Element("Publisher", Publisher);
  }

  if (!ProductUrl.empty()) {
    xout.Element("ProductUrl", ProductUrl);
  }

  // ApplicationIcon
  if (!InstallerApplicationIcon.empty()) {
    std::string name =
      cmSystemTools::GetFilenameName(InstallerApplicationIcon);
    std::string path = Directory + "/config/" + name;
    name = cmSystemTools::GetFilenameWithoutExtension(name);
    cmsys::SystemTools::CopyFileIfDifferent(InstallerApplicationIcon.data(),
                                            path.data());
    xout.Element("InstallerApplicationIcon", name);
  }

  // WindowIcon
  if (!InstallerWindowIcon.empty()) {
    std::string name = cmSystemTools::GetFilenameName(InstallerWindowIcon);
    std::string path = Directory + "/config/" + name;
    cmsys::SystemTools::CopyFileIfDifferent(InstallerWindowIcon.data(),
                                            path.data());
    xout.Element("InstallerWindowIcon", name);
  }

  // Logo
  if (!Logo.empty()) {
    std::string name = cmSystemTools::GetFilenameName(Logo);
    std::string path = Directory + "/config/" + name;
    cmsys::SystemTools::CopyFileIfDifferent(Logo.data(), path.data());
    xout.Element("Logo", name);
  }

  // Start menu
  if (!IsVersionLess("2.0")) {
    xout.Element("StartMenuDir", StartMenuDir);
  }

  // Target dir
  if (!TargetDir.empty()) {
    xout.Element("TargetDir", TargetDir);
  }

  // Admin target dir
  if (!AdminTargetDir.empty()) {
    xout.Element("AdminTargetDir", AdminTargetDir);
  }

  // Remote repositories
  if (!RemoteRepositories.empty()) {
    xout.StartElement("RemoteRepositories");
    for (RepositoriesVector::iterator rit = RemoteRepositories.begin();
         rit != RemoteRepositories.end(); ++rit) {
      (*rit)->WriteRepositoryConfig(xout);
    }
    xout.EndElement();
  }

  // Maintenance tool
  if (!IsVersionLess("2.0") && !MaintenanceToolName.empty()) {
    xout.Element("MaintenanceToolName", MaintenanceToolName);
  }

  // Maintenance tool ini file
  if (!IsVersionLess("2.0") && !MaintenanceToolIniFile.empty()) {
    xout.Element("MaintenanceToolIniFile", MaintenanceToolIniFile);
  }

  // Different allows
  if (IsVersionLess("2.0")) {
    // CPack IFW default policy
    xout.Comment("CPack IFW default policy for QtIFW less 2.0");
    xout.Element("AllowNonAsciiCharacters", "true");
    xout.Element("AllowSpaceInPath", "true");
  } else {
    if (!AllowNonAsciiCharacters.empty()) {
      xout.Element("AllowNonAsciiCharacters", AllowNonAsciiCharacters);
    }
    if (!AllowSpaceInPath.empty()) {
      xout.Element("AllowSpaceInPath", AllowSpaceInPath);
    }
  }

  // Control script (copy to config dir)
  if (!IsVersionLess("2.0") && !ControlScript.empty()) {
    std::string name = cmSystemTools::GetFilenameName(ControlScript);
    std::string path = Directory + "/config/" + name;
    cmsys::SystemTools::CopyFileIfDifferent(ControlScript.data(), path.data());
    xout.Element("ControlScript", name);
  }

  // Resources (copy to resources dir)
  if (!Resources.empty()) {
    std::vector<std::string> resources;
    cmCPackIFWResourcesParser parser(this);
    for (size_t i = 0; i < Resources.size(); i++) {
      if (parser.ParseResource(i)) {
        std::string name = cmSystemTools::GetFilenameName(Resources[i]);
        std::string path = Directory + "/resources/" + name;
        cmsys::SystemTools::CopyFileIfDifferent(Resources[i].data(),
                                                path.data());
        resources.push_back(name);
      } else {
        cmCPackLogger(cmCPackLog::LOG_WARNING, "Can't copy resources from \""
                        << Resources[i] << "\". Resource will be skipped."
                        << std::endl);
      }
    }
    Resources = resources;
  }

  xout.EndElement();
  xout.EndDocument();
}

void cmCPackIFWInstaller::GeneratePackageFiles()
{
  if (Packages.empty() || Generator->IsOnePackage()) {
    // Generate default package
    cmCPackIFWPackage package;
    package.Generator = Generator;
    package.Installer = this;
    // Check package group
    if (const char* option = GetOption("CPACK_IFW_PACKAGE_GROUP")) {
      package.ConfigureFromGroup(option);
      std::string forcedOption = "CPACK_IFW_COMPONENT_GROUP_" +
        cmsys::SystemTools::UpperCase(option) + "_FORCED_INSTALLATION";
      if (!GetOption(forcedOption)) {
        package.ForcedInstallation = "true";
      }
    } else {
      package.ConfigureFromOptions();
    }
    package.GeneratePackageFile();
    return;
  }

  // Generate packages meta information
  for (PackagesMap::iterator pit = Packages.begin(); pit != Packages.end();
       ++pit) {
    cmCPackIFWPackage* package = pit->second;
    package->GeneratePackageFile();
  }
}

void cmCPackIFWInstaller::WriteGeneratedByToStrim(cmXMLWriter& xout)
{
  if (Generator) {
    Generator->WriteGeneratedByToStrim(xout);
  }
}
