/* 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 <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;
}
