#include <cassert>
#include <cstdlib>
#include <iostream>
#include <string>
#include <unordered_map>

#include <args.hxx>


namespace param {
using namespace ::args;

ArgumentParser parser {
  "converter: feature indices + host -> stego"
};
HelpFlag help {
  parser, "help", "display this menu", {'h', "help"},
};

ValueFlag<size_t> dur {
  parser, "100", "duration", {"dur"}, 100,
};
ValueFlag<size_t> fnum {
  parser, "50", "number of feature code alphabet", {"fnum"}, 50,
};
ValueFlag<size_t> branch {
  parser, "2", "number of branch", {"branch"}, 2,
};

enum Algo {
  kIncrement,
};
const std::unordered_map<std::string, Algo> kAlgo = {
  {"inc", kIncrement},
};
MapFlag<std::string, Algo> algo {
  parser, "inc", "generator algorithm", {"algo", "algorithm"}, kAlgo,
};

Group inc {
  parser, "increment algorithm parameters"
};
ValueFlag<size_t> inc_min {
  inc, "0", "min stride of each move", {"inc-min"}, 0,
};
Flag inc_time {
  inc, "inc-time", "add current time value", {"inc-time"},
};

}  // namespace param


size_t Step(size_t t, size_t c, size_t b) {
  const auto fnum = args::get(param::fnum);

  size_t ret;
  switch (args::get(param::algo)) {
  case param::kIncrement:
    ret = c+b+args::get(param::inc_min);
    if (param::inc_time) {
      ret += t;
    }
    return ret%fnum;

  default:
    assert(false);
    std::abort();
  }
}

void Exec() {
  for (size_t t = 0; t < args::get(param::dur); ++t) {
    for (size_t c = 0; c < args::get(param::fnum); ++c) {
      for (size_t b = 0; b < args::get(param::branch); ++b) {
        std::cout << Step(t, c, b) << ' ';
      }
      std::cout << '\n';
    }
  }
}

int main(int argc, char** argv)
try {
  param::parser.ParseCLI(argc, argv);
  Exec();
  return EXIT_SUCCESS;
} catch (const args::Help&) {
  std::cout << param::parser << std::endl;
  return EXIT_SUCCESS;
} catch (const std::exception& e) {
  std::cerr << e.what() << std::endl;
  return EXIT_FAILURE;
}