#pragma once
#include <vector>
#include <string>

namespace matrix {

  typedef std::vector<int> Row;
  typedef std::vector<Row> Matrix;

  struct each_cell {
    size_t x = ~0;
    size_t y = ~0;
    size_t width = 0;
    size_t height = 0;

    each_cell(Matrix &mat);
    bool next();
  };

  struct each_row {
    Matrix &$mat;
    size_t x = ~0;
    size_t y = ~0;
    size_t width = 0;
    size_t height = 0;
    bool row = false;

    each_row(Matrix &mat);
    bool next();
  };

  struct in_box {
    size_t x = 0; // these are set in constructor
    size_t y = 0; // again, no fancy ~ trick needed
    size_t left = 0;
    size_t top = 0;
    size_t right = 0;
    size_t bottom = 0;

    in_box(Matrix &mat, size_t x, size_t y, size_t size);
    bool next();
    void dump();
  };

  /*
   * Just a quick thing to reset a matrix to a value.
   */
  inline void assign(Matrix &out, int new_value) {
    for(auto &row : out) {
      row.assign(row.size(), new_value);
    }
  }

  void dump(const std::string &msg, Matrix &map, int show_x=-1, int show_y=-1);
}
