struct Chunk {
  dimensions: [u16; 3],
  data: Vec<u16>,
  palette: Vec<String>,
}

impl Chunk {
  fn new (
    dimensions: [u16; 3]
  ) -> Chunk {
    let mut data = Vec::<u16>::new();
    let palette = Vec::<String>::new();

    data.resize((dimensions[0] * dimensions[1] * dimensions[2]) as usize, 0);
    Chunk {
      dimensions,
      data,
      palette
    }
  }

  fn pos_to_idx (&self, x: u16, y: u16, z: u16) -> usize {
    let [max_x, max_y, _] = self.dimensions;
    ((z * max_x * max_y) + (y * max_y) + x) as usize
  }

  fn idx_to_pos (&self, idx: usize) -> (u16, u16, u16) {
    let [max_x, max_y, _] = self.dimensions;

    let z = idx as u16 / (max_x * max_y);
    let i2 = idx as u16 - (z * max_x * max_y);
    let y = i2 / max_x;
    let x = i2 % max_x;

    (x, y, z)
  }

  fn set_at_pos (&mut self, x: u16, y: u16, z: u16, name: String) {
    let idx = self.pos_to_idx(x, y, z);
    self.set_at_idx(idx, name)
  }

  fn set_at_idx (&mut self, idx: usize, name: String) {
    let voxel_id;

    if let Some(i) = self.palette.iter().position(|palette_name| palette_name == &name) {
      voxel_id = i;
    } else {
      self.palette.push(name);
      voxel_id = self.palette.len() - 1;
    }

    self.data[idx] = voxel_id as u16;
  }
}

struct ChunkMap {

}
