/* 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/string_view>
#include <cmext/string_view>

#include "cmExecutionStatus.h"
#include "cmFunctionBlocker.h"
#include "cmListFileCache.h"
#include "cmMakefile.h"
#include "cmMessageType.h"
#include "cmProperty.h"
#include "cmRange.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.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
  std::string oldDef;
  if (cmProp d = mf.GetDefinition(this->Args.front())) {
    oldDef = *d;
  }

  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) {
    // restore the variable to its prior value
    mf.AddDefinition(this->Args.front(), oldDef);
  }
  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<std::vector<std::string>> 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)) {
    std::vector<std::string> items;
    auto const& value = mf.GetSafeDefinition(var);
    if (!value.empty()) {
      cmExpandList(value, items, true);
    }
    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, std::string> oldDefs;
  for (auto i = 0u; i < values.size(); ++i) {
    if (cmProp d = mf.GetDefinition(iterationVars[i])) {
      oldDefs.emplace(iterationVars[i], *d);
    }
  }

  // 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) {
      mf.AddDefinition(p.first, p.second);
    }
  }
  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();
      result.Break = true;
      break;
    }
    if (status.GetBreakInvoked()) {
      result.Break = true;
      break;
    }
    if (status.GetContinueInvoked()) {
      break;
    }
    if (cmSystemTools::GetFatalErrorOccured()) {
      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, true);
      }

    } 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::SetFatalErrorOccured();
    return false;
  } catch (std::out_of_range&) {
    std::ostringstream e;
    e << "Integer out of range: '" << str << "'";
    status.SetError(e.str());
    cmSystemTools::SetFatalErrorOccured();
    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::SetFatalErrorOccured();
        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 +
        int(start < stop) * (stop - start) / std::abs(step) +
        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;
}
