/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
   file LICENSE.rst 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 <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(std::size_t const 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());
    auto const iter_var_prefix = cmStrCat(this->Args.front(), '_');
    auto i = 0u;
    std::generate(
      iterationVars.begin(), iterationVars.end(),
      [&]() -> std::string { return cmStrCat(iter_var_prefix, 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) {
    auto const& 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 (status.HasExitCode()) {
      inStatus.SetExitCode(status.GetExitCode());
      result.Break = true;
      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
  auto const 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 ", varsCount,
                                   " list variables, but given ",
                                   fb->Args.size() - varsCount));
    return true;
  }

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

  return true;
}

bool TryParseInteger(cmExecutionStatus& status, std::string const& str, int& i)
{
  try {
    i = std::stoi(str);
  } catch (std::invalid_argument const&) {
    status.SetError(cmStrCat("Invalid integer: '", str, '\''));
    cmSystemTools::SetFatalErrorOccurred();
    return false;
  } catch (std::out_of_range const&) {
    status.SetError(cmStrCat("Integer out of range: '", 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...
      std::size_t const 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;
}
