/*============================================================================
  CMake - Cross Platform Makefile Generator
  Copyright 2012 Stephen Kelly <steveire@gmail.com>

  Distributed under the OSI-approved BSD License (the "License");
  see accompanying file Copyright.txt for details.

  This software is distributed WITHOUT ANY WARRANTY; without even the
  implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  See the License for more information.
============================================================================*/
#include "cmGeneratorExpressionEvaluator.h"

#include "cmAlgorithms.h"
#include "cmGeneratorExpression.h"
#include "cmGeneratorExpressionDAGChecker.h"
#include "cmGeneratorExpressionParser.h"
#include "cmGlobalGenerator.h"
#include "cmLocalGenerator.h"
#include "cmMakefile.h"
#include "cmSourceFile.h"

#include <cmsys/String.h>

#include <assert.h>
#include <errno.h>

#include "cmGeneratorExpressionNode.h"

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

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<std::vector<cmGeneratorExpressionEvaluator*> >::const_iterator
    pit) const
{
  std::string result;

  const std::vector<
    std::vector<cmGeneratorExpressionEvaluator*> >::const_iterator pend =
    this->ParamChildren.end();
  for (; pit != pend; ++pit) {
    std::vector<cmGeneratorExpressionEvaluator*>::const_iterator it =
      pit->begin();
    const std::vector<cmGeneratorExpressionEvaluator*>::const_iterator end =
      pit->end();
    for (; it != end; ++it) {
      if (node->RequiresLiteralInput()) {
        if ((*it)->GetType() != cmGeneratorExpressionEvaluator::Text) {
          reportError(context, this->GetOriginalExpression(), "$<" +
                        identifier + "> expression requires literal input.");
          return std::string();
        }
      }
      result += (*it)->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;
  {
    std::vector<cmGeneratorExpressionEvaluator*>::const_iterator it =
      this->IdentifierChildren.begin();
    const std::vector<cmGeneratorExpressionEvaluator*>::const_iterator end =
      this->IdentifierChildren.end();
    for (; it != end; ++it) {
      identifier += (*it)->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();
  {
    std::vector<std::vector<cmGeneratorExpressionEvaluator*> >::const_iterator
      pit = this->ParamChildren.begin();
    const std::vector<
      std::vector<cmGeneratorExpressionEvaluator*> >::const_iterator pend =
      this->ParamChildren.end();
    const bool acceptsArbitraryContent =
      node->AcceptsArbitraryContentParameter();
    int counter = 1;
    for (; pit != pend; ++pit, ++counter) {
      if (acceptsArbitraryContent && counter == numExpected) {
        std::string lastParam = this->ProcessArbitraryContent(
          node, identifier, context, dagChecker, pit);
        parameters.push_back(lastParam);
        return std::string();
      } else {
        std::string parameter;
        std::vector<cmGeneratorExpressionEvaluator*>::const_iterator it =
          pit->begin();
        const std::vector<cmGeneratorExpressionEvaluator*>::const_iterator
          end = pit->end();
        for (; it != end; ++it) {
          parameter += (*it)->Evaluate(context, dagChecker);
          if (context->HadError) {
            return std::string();
          }
        }
        parameters.push_back(parameter);
      }
    }
  }

  if ((numExpected > cmGeneratorExpressionNode::DynamicParameters &&
       (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.");
  }
  if (numExpected == cmGeneratorExpressionNode::OneOrZeroParameters &&
      parameters.size() > 1) {
    reportError(context, this->GetOriginalExpression(), "$<" + identifier +
                  "> expression requires one or zero parameters.");
  }
  return std::string();
}

GeneratorExpressionContent::~GeneratorExpressionContent()
{
  cmDeleteAll(this->IdentifierChildren);
  std::for_each(this->ParamChildren.begin(), this->ParamChildren.end(),
                cmDeleteAll<std::vector<cmGeneratorExpressionEvaluator*> >);
}
