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

#include <algorithm>
#include <cassert>
#include <cstddef> // IWYU pragma: keep
// NOTE The declaration of `std::abs` has moved to `cmath` since C++17
// See https://en.cppreference.com/w/cpp/numeric/math/abs
// ALERT But IWYU used to lint `#include`s do not "understand"
// conditional compilation (i.e. `#if __cplusplus >= 201703L`)
#include <cstdlib>
#include <iterator>
#include <map>
#include <sstream>
#include <stdexcept>
#include <utility>

#include <cm/memory>
#include <cm/optional>
#include <cm/string_view>
#include <cmext/string_view>

#include "cmExecutionStatus.h"
#include "cmFunctionBlocker.h"
#include "cmList.h"
#include "cmListFileCache.h"
#include "cmMakefile.h"
#include "cmMessageType.h"
#include "cmPolicies.h"
#include "cmRange.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmValue.h"

namespace {
class cmForEachFunctionBlocker : public cmFunctionBlocker
{
public:
  explicit cmForEachFunctionBlocker(cmMakefile* mf);
  ~cmForEachFunctionBlocker() override;

  cm::string_view StartCommandName() const override { return "foreach"_s; }
  cm::string_view EndCommandName() const override { return "endforeach"_s; }

  bool ArgumentsMatch(cmListFileFunction const& lff,
                      cmMakefile& mf) const override;

  bool Replay(std::vector<cmListFileFunction> functions,
              cmExecutionStatus& inStatus) override;

  void SetIterationVarsCount(const std::size_t varsCount)
  {
    this->IterationVarsCount = varsCount;
  }
  void SetZipLists() { this->ZipLists = true; }

  std::vector<std::string> Args;

private:
  struct InvokeResult
  {
    bool Restore;
    bool Break;
  };

  bool ReplayItems(std::vector<cmListFileFunction> const& functions,
                   cmExecutionStatus& inStatus);

  bool ReplayZipLists(std::vector<cmListFileFunction> const& functions,
                      cmExecutionStatus& inStatus);

  InvokeResult invoke(std::vector<cmListFileFunction> const& functions,
                      cmExecutionStatus& inStatus, cmMakefile& mf);

  cmMakefile* Makefile;
  std::size_t IterationVarsCount = 0u;
  bool ZipLists = false;
};

cmForEachFunctionBlocker::cmForEachFunctionBlocker(cmMakefile* mf)
  : Makefile(mf)
{
  this->Makefile->PushLoopBlock();
}

cmForEachFunctionBlocker::~cmForEachFunctionBlocker()
{
  this->Makefile->PopLoopBlock();
}

bool cmForEachFunctionBlocker::ArgumentsMatch(cmListFileFunction const& lff,
                                              cmMakefile& mf) const
{
  std::vector<std::string> expandedArguments;
  mf.ExpandArguments(lff.Arguments(), expandedArguments);
  return expandedArguments.empty() ||
    expandedArguments.front() == this->Args.front();
}

bool cmForEachFunctionBlocker::Replay(
  std::vector<cmListFileFunction> functions, cmExecutionStatus& inStatus)
{
  return this->ZipLists ? this->ReplayZipLists(functions, inStatus)
                        : this->ReplayItems(functions, inStatus);
}

bool cmForEachFunctionBlocker::ReplayItems(
  std::vector<cmListFileFunction> const& functions,
  cmExecutionStatus& inStatus)
{
  assert("Unexpected number of iteration variables" &&
         this->IterationVarsCount == 1);

  auto& mf = inStatus.GetMakefile();

  // At end of for each execute recorded commands
  // store the old value
  cm::optional<std::string> oldDef;
  if (mf.GetPolicyStatus(cmPolicies::CMP0124) != cmPolicies::NEW) {
    oldDef = mf.GetSafeDefinition(this->Args.front());
  } else if (mf.IsNormalDefinitionSet(this->Args.front())) {
    oldDef = *mf.GetDefinition(this->Args.front());
  }

  auto restore = false;
  for (std::string const& arg : cmMakeRange(this->Args).advance(1)) {
    // Set the variable to the loop value
    mf.AddDefinition(this->Args.front(), arg);
    // Invoke all the functions that were collected in the block.
    auto r = this->invoke(functions, inStatus, mf);
    restore = r.Restore;
    if (r.Break) {
      break;
    }
  }

  if (restore) {
    if (oldDef) {
      // restore the variable to its prior value
      mf.AddDefinition(this->Args.front(), *oldDef);
    } else {
      mf.RemoveDefinition(this->Args.front());
    }
  }

  return true;
}

bool cmForEachFunctionBlocker::ReplayZipLists(
  std::vector<cmListFileFunction> const& functions,
  cmExecutionStatus& inStatus)
{
  assert("Unexpected number of iteration variables" &&
         this->IterationVarsCount >= 1);

  auto& mf = inStatus.GetMakefile();

  // Expand the list of list-variables into a list of lists of strings
  std::vector<cmList> values;
  values.reserve(this->Args.size() - this->IterationVarsCount);
  // Also track the longest list size
  std::size_t maxItems = 0u;
  for (auto const& var :
       cmMakeRange(this->Args).advance(this->IterationVarsCount)) {
    cmList items;
    auto const& value = mf.GetSafeDefinition(var);
    if (!value.empty()) {
      items.assign(value, cmList::EmptyElements::Yes);
    }
    maxItems = std::max(maxItems, items.size());
    values.emplace_back(std::move(items));
  }

  // Form the list of iteration variables
  std::vector<std::string> iterationVars;
  if (this->IterationVarsCount > 1) {
    // If multiple iteration variables has given,
    // just copy them to the `iterationVars` list.
    iterationVars.reserve(values.size());
    std::copy(this->Args.begin(),
              this->Args.begin() + this->IterationVarsCount,
              std::back_inserter(iterationVars));
  } else {
    // In case of the only iteration variable,
    // generate names as `var_name_N`,
    // where `N` is the count of lists to zip
    iterationVars.resize(values.size());
    const auto iter_var_prefix = this->Args.front() + "_";
    auto i = 0u;
    std::generate(
      iterationVars.begin(), iterationVars.end(),
      [&]() -> std::string { return iter_var_prefix + std::to_string(i++); });
  }
  assert("Sanity check" && iterationVars.size() == values.size());

  // Store old values for iteration variables
  std::map<std::string, cm::optional<std::string>> oldDefs;
  for (auto i = 0u; i < values.size(); ++i) {
    const auto& varName = iterationVars[i];
    if (mf.GetPolicyStatus(cmPolicies::CMP0124) != cmPolicies::NEW) {
      oldDefs.emplace(varName, mf.GetSafeDefinition(varName));
    } else if (mf.IsNormalDefinitionSet(varName)) {
      oldDefs.emplace(varName, *mf.GetDefinition(varName));
    } else {
      oldDefs.emplace(varName, cm::nullopt);
    }
  }

  // Form a vector of current positions in all lists (Ok, vectors) of values
  std::vector<decltype(values)::value_type::iterator> positions;
  positions.reserve(values.size());
  std::transform(
    values.begin(), values.end(), std::back_inserter(positions),
    // Set the initial position to the beginning of every list
    [](decltype(values)::value_type& list) { return list.begin(); });
  assert("Sanity check" && positions.size() == values.size());

  auto restore = false;
  // Iterate over all the lists simulateneously
  for (auto i = 0u; i < maxItems; ++i) {
    // Declare iteration variables
    for (auto j = 0u; j < values.size(); ++j) {
      // Define (or not) the iteration variable if the current position
      // still not at the end...
      if (positions[j] != values[j].end()) {
        mf.AddDefinition(iterationVars[j], *positions[j]);
        ++positions[j];
      } else {
        mf.RemoveDefinition(iterationVars[j]);
      }
    }
    // Invoke all the functions that were collected in the block.
    auto r = this->invoke(functions, inStatus, mf);
    restore = r.Restore;
    if (r.Break) {
      break;
    }
  }

  // Restore the variables to its prior value
  if (restore) {
    for (auto const& p : oldDefs) {
      if (p.second) {
        mf.AddDefinition(p.first, *p.second);
      } else {
        mf.RemoveDefinition(p.first);
      }
    }
  }
  return true;
}

auto cmForEachFunctionBlocker::invoke(
  std::vector<cmListFileFunction> const& functions,
  cmExecutionStatus& inStatus, cmMakefile& mf) -> InvokeResult
{
  InvokeResult result = { true, false };
  // Invoke all the functions that were collected in the block.
  for (cmListFileFunction const& func : functions) {
    cmExecutionStatus status(mf);
    mf.ExecuteCommand(func, status);
    if (status.GetReturnInvoked()) {
      inStatus.SetReturnInvoked(status.GetReturnVariables());
      result.Break = true;
      break;
    }
    if (status.GetBreakInvoked()) {
      result.Break = true;
      break;
    }
    if (status.GetContinueInvoked()) {
      break;
    }
    if (cmSystemTools::GetFatalErrorOccurred()) {
      result.Restore = false;
      result.Break = true;
      break;
    }
  }
  return result;
}

bool HandleInMode(std::vector<std::string> const& args,
                  std::vector<std::string>::const_iterator kwInIter,
                  cmMakefile& makefile)
{
  assert("A valid iterator expected" && kwInIter != args.end());

  auto fb = cm::make_unique<cmForEachFunctionBlocker>(&makefile);

  // Copy iteration variable names first
  std::copy(args.begin(), kwInIter, std::back_inserter(fb->Args));
  // Remember the count of given iteration variable names
  const auto varsCount = fb->Args.size();
  fb->SetIterationVarsCount(varsCount);

  enum Doing
  {
    DoingNone,
    DoingLists,
    DoingItems,
    DoingZipLists
  };
  Doing doing = DoingNone;
  // Iterate over arguments past the "IN" keyword
  for (std::string const& arg : cmMakeRange(++kwInIter, args.end())) {
    if (arg == "LISTS") {
      if (doing == DoingZipLists) {
        makefile.IssueMessage(MessageType::FATAL_ERROR,
                              "ZIP_LISTS can not be used with LISTS or ITEMS");
        return true;
      }
      if (varsCount != 1u) {
        makefile.IssueMessage(
          MessageType::FATAL_ERROR,
          "ITEMS or LISTS require exactly one iteration variable");
        return true;
      }
      doing = DoingLists;

    } else if (arg == "ITEMS") {
      if (doing == DoingZipLists) {
        makefile.IssueMessage(MessageType::FATAL_ERROR,
                              "ZIP_LISTS can not be used with LISTS or ITEMS");
        return true;
      }
      if (varsCount != 1u) {
        makefile.IssueMessage(
          MessageType::FATAL_ERROR,
          "ITEMS or LISTS require exactly one iteration variable");
        return true;
      }
      doing = DoingItems;

    } else if (arg == "ZIP_LISTS") {
      if (doing != DoingNone) {
        makefile.IssueMessage(MessageType::FATAL_ERROR,
                              "ZIP_LISTS can not be used with LISTS or ITEMS");
        return true;
      }
      doing = DoingZipLists;
      fb->SetZipLists();

    } else if (doing == DoingLists) {
      auto const& value = makefile.GetSafeDefinition(arg);
      if (!value.empty()) {
        cmExpandList(value, fb->Args, cmList::EmptyElements::Yes);
      }

    } else if (doing == DoingItems || doing == DoingZipLists) {
      fb->Args.push_back(arg);

    } else {
      makefile.IssueMessage(MessageType::FATAL_ERROR,
                            cmStrCat("Unknown argument:\n", "  ", arg, "\n"));
      return true;
    }
  }

  // If `ZIP_LISTS` given and variables count more than 1,
  // make sure the given lists count matches variables...
  if (doing == DoingZipLists && varsCount > 1u &&
      (2u * varsCount) != fb->Args.size()) {
    makefile.IssueMessage(
      MessageType::FATAL_ERROR,
      cmStrCat("Expected ", std::to_string(varsCount),
               " list variables, but given ",
               std::to_string(fb->Args.size() - varsCount)));
    return true;
  }

  makefile.AddFunctionBlocker(std::move(fb));

  return true;
}

bool TryParseInteger(cmExecutionStatus& status, const std::string& str, int& i)
{
  try {
    i = std::stoi(str);
  } catch (std::invalid_argument&) {
    std::ostringstream e;
    e << "Invalid integer: '" << str << "'";
    status.SetError(e.str());
    cmSystemTools::SetFatalErrorOccurred();
    return false;
  } catch (std::out_of_range&) {
    std::ostringstream e;
    e << "Integer out of range: '" << str << "'";
    status.SetError(e.str());
    cmSystemTools::SetFatalErrorOccurred();
    return false;
  }

  return true;
}

} // anonymous namespace

bool cmForEachCommand(std::vector<std::string> const& args,
                      cmExecutionStatus& status)
{
  if (args.empty()) {
    status.SetError("called with incorrect number of arguments");
    return false;
  }
  auto kwInIter = std::find(args.begin(), args.end(), "IN");
  if (kwInIter != args.end()) {
    return HandleInMode(args, kwInIter, status.GetMakefile());
  }

  // create a function blocker
  auto fb = cm::make_unique<cmForEachFunctionBlocker>(&status.GetMakefile());
  if (args.size() > 1) {
    if (args[1] == "RANGE") {
      int start = 0;
      int stop = 0;
      int step = 0;
      if (args.size() == 3) {
        if (!TryParseInteger(status, args[2], stop)) {
          return false;
        }
      }
      if (args.size() == 4) {
        if (!TryParseInteger(status, args[2], start)) {
          return false;
        }
        if (!TryParseInteger(status, args[3], stop)) {
          return false;
        }
      }
      if (args.size() == 5) {
        if (!TryParseInteger(status, args[2], start)) {
          return false;
        }
        if (!TryParseInteger(status, args[3], stop)) {
          return false;
        }
        if (!TryParseInteger(status, args[4], step)) {
          return false;
        }
      }
      if (step == 0) {
        if (start > stop) {
          step = -1;
        } else {
          step = 1;
        }
      }
      if ((start > stop && step > 0) || (start < stop && step < 0) ||
          step == 0) {
        status.SetError(
          cmStrCat("called with incorrect range specification: start ", start,
                   ", stop ", stop, ", step ", step));
        cmSystemTools::SetFatalErrorOccurred();
        return false;
      }

      // Calculate expected iterations count and reserve enough space
      // in the `fb->Args` vector. The first item is the iteration variable
      // name...
      const std::size_t iter_cnt = 2u +
        static_cast<int>(start < stop) * (stop - start) / std::abs(step) +
        static_cast<int>(start > stop) * (start - stop) / std::abs(step);
      fb->Args.resize(iter_cnt);
      fb->Args.front() = args.front();
      auto cc = start;
      auto generator = [&cc, step]() -> std::string {
        auto result = std::to_string(cc);
        cc += step;
        return result;
      };
      // Fill the `range` vector w/ generated string values
      // (starting from 2nd position)
      std::generate(++fb->Args.begin(), fb->Args.end(), generator);
    } else {
      fb->Args = args;
    }
  } else {
    fb->Args = args;
  }

  fb->SetIterationVarsCount(1u);
  status.GetMakefile().AddFunctionBlocker(std::move(fb));

  return true;
}
