// tilemap

function tilemap()
{
  this.tiles = [];
  this.offset_x = 0;
  this.offset_y = 0;
  this.size_x = 32;
  this.size_y = 32;
  return this;
}

tilemap.for = function (map, fn) {
  for (var x = 0; x < map.tiles.length; x++) {
    if (!map.tiles[x]) continue;
    for (var y = 0; y < map.tiles[x].length; y++) {
      if (map.tiles[x][y] != null) {
        var result = fn(map.tiles[x][y], {
          x: x + map.offset_x,
          y: y + map.offset_y
        });
        if (result != null) {
          map.tiles[x][y] = result;
        }
      }
    }
  }
}

tilemap.prototype =
{
  at(pos) {
    var x = pos.x - this.offset_x;
    var y = pos.y - this.offset_y;
    if (!this.tiles[x]) return null;
    return this.tiles[x][y];
  },
  
  set(pos, image) {
    // Shift arrays if negative indices
    if (pos.x < this.offset_x) {
      var shift = this.offset_x - pos.x;
      var new_tiles = [];
      for (var i = 0; i < shift; i++) new_tiles[i] = [];
      this.tiles = new_tiles.concat(this.tiles);
      this.offset_x = pos.x;
    }
    
    if (pos.y < this.offset_y) {
      var shift = this.offset_y - pos.y;
      for (var i = 0; i < this.tiles.length; i++) {
        if (!this.tiles[i]) this.tiles[i] = [];
        var new_col = [];
        for (var j = 0; j < shift; j++) new_col[j] = null;
        this.tiles[i] = new_col.concat(this.tiles[i]);
      }
      this.offset_y = pos.y;
    }
    
    var x = pos.x - this.offset_x;
    var y = pos.y - this.offset_y;
    
    // Ensure array exists up to x
    while (this.tiles.length <= x) this.tiles.push([]);
    
    // Set the value
    this.tiles[x][y] = image;
  },
  
  draw() {
    return {
      cmd:'tilemap',
      tilemap:this
    }
  },
}

return tilemap