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

#include <utility>

#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"

cmScriptGenerator::cmScriptGenerator(std::string config_var,
                                     std::vector<std::string> configurations)
  : RuntimeConfigVariable(std::move(config_var))
  , Configurations(std::move(configurations))
  , ConfigurationName("")
  , ConfigurationTypes(nullptr)
  , ActionsPerConfig(false)
{
}

cmScriptGenerator::~cmScriptGenerator() = default;

void cmScriptGenerator::Generate(
  std::ostream& os, const std::string& config,
  std::vector<std::string> const& configurationTypes)
{
  this->ConfigurationName = config;
  this->ConfigurationTypes = &configurationTypes;
  this->GenerateScript(os);
  this->ConfigurationName.clear();
  this->ConfigurationTypes = nullptr;
}

static void cmScriptGeneratorEncodeConfig(const std::string& config,
                                          std::string& result)
{
  for (const char* c = config.c_str(); *c; ++c) {
    if (*c >= 'a' && *c <= 'z') {
      result += "[";
      result += static_cast<char>(*c + 'A' - 'a');
      result += *c;
      result += "]";
    } else if (*c >= 'A' && *c <= 'Z') {
      result += "[";
      result += *c;
      result += static_cast<char>(*c + 'a' - 'A');
      result += "]";
    } else {
      result += *c;
    }
  }
}

std::string cmScriptGenerator::CreateConfigTest(const std::string& config)
{
  std::string result =
    cmStrCat("\"${", this->RuntimeConfigVariable, "}\" MATCHES \"^(");
  if (!config.empty()) {
    cmScriptGeneratorEncodeConfig(config, result);
  }
  result += ")$\"";
  return result;
}

std::string cmScriptGenerator::CreateConfigTest(
  std::vector<std::string> const& configs)
{
  std::string result =
    cmStrCat("\"${", this->RuntimeConfigVariable, "}\" MATCHES \"^(");
  const char* sep = "";
  for (std::string const& config : configs) {
    result += sep;
    sep = "|";
    cmScriptGeneratorEncodeConfig(config, result);
  }
  result += ")$\"";
  return result;
}

void cmScriptGenerator::GenerateScript(std::ostream& os)
{
  // Track indentation.
  Indent indent;

  // Generate the script possibly with per-configuration code.
  this->GenerateScriptConfigs(os, indent);
}

void cmScriptGenerator::GenerateScriptConfigs(std::ostream& os, Indent indent)
{
  if (this->ActionsPerConfig) {
    this->GenerateScriptActionsPerConfig(os, indent);
  } else {
    this->GenerateScriptActionsOnce(os, indent);
  }
}

void cmScriptGenerator::GenerateScriptActions(std::ostream& os, Indent indent)
{
  if (this->ActionsPerConfig) {
    // This is reached for single-configuration build generators in a
    // per-config script generator.
    this->GenerateScriptForConfig(os, this->ConfigurationName, indent);
  }
}

void cmScriptGenerator::GenerateScriptForConfig(std::ostream& /*unused*/,
                                                const std::string& /*unused*/,
                                                Indent /*unused*/)
{
  // No actions for this generator.
}

bool cmScriptGenerator::GeneratesForConfig(const std::string& config)
{
  // If this is not a configuration-specific rule then we install.
  if (this->Configurations.empty()) {
    return true;
  }

  // This is a configuration-specific rule.  Check if the config
  // matches this rule.
  std::string config_upper = cmSystemTools::UpperCase(config);
  for (std::string const& cfg : this->Configurations) {
    if (cmSystemTools::UpperCase(cfg) == config_upper) {
      return true;
    }
  }
  return false;
}

void cmScriptGenerator::GenerateScriptActionsOnce(std::ostream& os,
                                                  Indent indent)
{
  if (this->Configurations.empty()) {
    // This rule is for all configurations.
    this->GenerateScriptActions(os, indent);
  } else {
    // Generate a per-configuration block.
    std::string config_test = this->CreateConfigTest(this->Configurations);
    os << indent << "if(" << config_test << ")\n";
    this->GenerateScriptActions(os, indent.Next());
    os << indent << "endif(" << config_test << ")\n";
  }
}

void cmScriptGenerator::GenerateScriptActionsPerConfig(std::ostream& os,
                                                       Indent indent)
{
  if (this->ConfigurationTypes->empty()) {
    // In a single-configuration generator there is only one action
    // and it applies if the runtime-requested configuration is among
    // the rule's allowed configurations.  The configuration built in
    // the tree does not matter for this decision but will be used to
    // generate proper target file names into the code.
    this->GenerateScriptActionsOnce(os, indent);
  } else {
    // In a multi-configuration generator we produce a separate rule
    // in a block for each configuration that is built.  We restrict
    // the list of configurations to those to which this rule applies.
    bool first = true;
    for (std::string const& cfgType : *this->ConfigurationTypes) {
      if (this->GeneratesForConfig(cfgType)) {
        // Generate a per-configuration block.
        std::string config_test = this->CreateConfigTest(cfgType);
        os << indent << (first ? "if(" : "elseif(") << config_test << ")\n";
        this->GenerateScriptForConfig(os, cfgType, indent.Next());
        first = false;
      }
    }
    if (!first) {
      if (this->NeedsScriptNoConfig()) {
        os << indent << "else()\n";
        this->GenerateScriptNoConfig(os, indent.Next());
      }
      os << indent << "endif()\n";
    }
  }
}
