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

#include <sstream>

#include "cmGeneratorExpressionContext.h"
#include "cmGeneratorExpressionNode.h"

GeneratorExpressionContent::GeneratorExpressionContent(
  const char* startContent, size_t length)
  : StartContent(startContent)
  , ContentLength(length)
{
}

GeneratorExpressionContent::~GeneratorExpressionContent() = default;

std::string GeneratorExpressionContent::GetOriginalExpression() const
{
  return std::string(this->StartContent, this->ContentLength);
}

std::string GeneratorExpressionContent::ProcessArbitraryContent(
  const cmGeneratorExpressionNode* node, const std::string& identifier,
  cmGeneratorExpressionContext* context,
  cmGeneratorExpressionDAGChecker* dagChecker,
  std::vector<cmGeneratorExpressionEvaluatorVector>::const_iterator pit) const
{
  std::string result;

  const auto pend = this->ParamChildren.end();
  for (; pit != pend; ++pit) {
    for (auto& pExprEval : *pit) {
      if (node->RequiresLiteralInput()) {
        if (pExprEval->GetType() != cmGeneratorExpressionEvaluator::Text) {
          reportError(context, this->GetOriginalExpression(),
                      "$<" + identifier +
                        "> expression requires literal input.");
          return std::string();
        }
      }
      result += pExprEval->Evaluate(context, dagChecker);
      if (context->HadError) {
        return std::string();
      }
    }
    if ((pit + 1) != pend) {
      result += ",";
    }
  }
  if (node->RequiresLiteralInput()) {
    std::vector<std::string> parameters;
    parameters.push_back(result);
    return node->Evaluate(parameters, context, this, dagChecker);
  }
  return result;
}

std::string GeneratorExpressionContent::Evaluate(
  cmGeneratorExpressionContext* context,
  cmGeneratorExpressionDAGChecker* dagChecker) const
{
  std::string identifier;
  {
    for (auto& pExprEval : this->IdentifierChildren) {
      identifier += pExprEval->Evaluate(context, dagChecker);
      if (context->HadError) {
        return std::string();
      }
    }
  }

  const cmGeneratorExpressionNode* node =
    cmGeneratorExpressionNode::GetNode(identifier);

  if (!node) {
    reportError(context, this->GetOriginalExpression(),
                "Expression did not evaluate to a known generator expression");
    return std::string();
  }

  if (!node->GeneratesContent()) {
    if (node->NumExpectedParameters() == 1 &&
        node->AcceptsArbitraryContentParameter()) {
      if (this->ParamChildren.empty()) {
        reportError(context, this->GetOriginalExpression(),
                    "$<" + identifier + "> expression requires a parameter.");
      }
    } else {
      std::vector<std::string> parameters;
      this->EvaluateParameters(node, identifier, context, dagChecker,
                               parameters);
    }
    return std::string();
  }

  std::vector<std::string> parameters;
  this->EvaluateParameters(node, identifier, context, dagChecker, parameters);
  if (context->HadError) {
    return std::string();
  }

  return node->Evaluate(parameters, context, this, dagChecker);
}

std::string GeneratorExpressionContent::EvaluateParameters(
  const cmGeneratorExpressionNode* node, const std::string& identifier,
  cmGeneratorExpressionContext* context,
  cmGeneratorExpressionDAGChecker* dagChecker,
  std::vector<std::string>& parameters) const
{
  const int numExpected = node->NumExpectedParameters();
  {
    auto pit = this->ParamChildren.begin();
    const auto pend = this->ParamChildren.end();
    const bool acceptsArbitraryContent =
      node->AcceptsArbitraryContentParameter();
    int counter = 1;
    for (; pit != pend; ++pit, ++counter) {
      if (acceptsArbitraryContent && counter == numExpected) {
        parameters.push_back(this->ProcessArbitraryContent(
          node, identifier, context, dagChecker, pit));
        return std::string();
      }
      std::string parameter;
      for (auto& pExprEval : *pit) {
        parameter += pExprEval->Evaluate(context, dagChecker);
        if (context->HadError) {
          return std::string();
        }
      }
      parameters.push_back(std::move(parameter));
    }
  }

  if ((numExpected > cmGeneratorExpressionNode::DynamicParameters &&
       static_cast<unsigned int>(numExpected) != parameters.size())) {
    if (numExpected == 0) {
      reportError(context, this->GetOriginalExpression(),
                  "$<" + identifier + "> expression requires no parameters.");
    } else if (numExpected == 1) {
      reportError(context, this->GetOriginalExpression(),
                  "$<" + identifier +
                    "> expression requires "
                    "exactly one parameter.");
    } else {
      std::ostringstream e;
      e << "$<" + identifier + "> expression requires " << numExpected
        << " comma separated parameters, but got " << parameters.size()
        << " instead.";
      reportError(context, this->GetOriginalExpression(), e.str());
    }
    return std::string();
  }

  if (numExpected == cmGeneratorExpressionNode::OneOrMoreParameters &&
      parameters.empty()) {
    reportError(context, this->GetOriginalExpression(),
                "$<" + identifier +
                  "> expression requires at least one parameter.");
  } else if (numExpected == cmGeneratorExpressionNode::TwoOrMoreParameters &&
             parameters.size() < 2) {
    reportError(context, this->GetOriginalExpression(),
                "$<" + identifier +
                  "> expression requires at least two parameters.");
  } else if (numExpected == cmGeneratorExpressionNode::OneOrZeroParameters &&
             parameters.size() > 1) {
    reportError(context, this->GetOriginalExpression(),
                "$<" + identifier +
                  "> expression requires one or zero parameters.");
  }
  return std::string();
}
