// Generate fake pixel data, as if sreenshotting a canvas element.
//
// The RGB channels are repurposed to indicate the function they were created by
// and their position in their 1 dimensionsal array structure.
//
// If a [R, G, B] contains a non-zero value the following applies;
//   R: The pixel's colour is due to text and was generated by withText()
//   G: The pixel's colour is due to background and was generated by withText()
//   B: The pixel's colour is due to background and was generated by withoutText()
//
//   * The values express the pixel's position in the array.
//   * G and B should always have the same values, but should never appear in the same
//     [R, G, B] array.
export default class CanvasPixels {
  constructor(dimensions) {
    this.width = dimensions.dom.sub.width;
    this.height = dimensions.dom.sub.height;
    this.pixel_count = this.width * this.height * 4;
  }

  // Putting the index in the red channel indicates text. An index value in the green
  // channel indicates that this is the withText() function yet the colour is being
  // picked up from the background (as if it were the withoutText() function).
  with_text() {
    let x, y, index;
    let pixels = [];
    for (let i = 0; i < this.pixel_count; i += 4) {
      x = (i / 4) % this.width;
      y = Math.floor(i / 2 / 4 / this.width);
      index = this._getIndexValue(i);
      if (this._checkForCharacter(x, y)) {
        pixels.push(index);
        pixels.push(0);
      } else {
        pixels.push(0);
        pixels.push(index);
      }
      pixels.push(0);
      pixels.push(0);
    }
    return { data: pixels };
  }

  _getIndexValue(i) {
    // Add 1 to distinguish the zero value. Because zero values mean that nothing was
    // found.
    return i / 4 + 1;
  }

  _checkForCharacter(x, y) {
    const char = global.mock_DOM_text[y].charAt(x);
    const mask_char = global.mock_DOM_template[y].charAt(x);
    const isCharThere = !this._isNullOrWhiteSpace(char);
    const isMaskThere = mask_char === "!";
    return isCharThere && !isMaskThere;
  }

  _isNullOrWhiteSpace(str) {
    return !str || str.length === 0 || /^\s*$/.test(str);
  }

  // Using the blue channel indicates that this sample was taken from the withoutText()
  // function.
  without_text() {
    let pixels = [];
    for (let i = 0; i < this.pixel_count; i += 4) {
      pixels.push(0);
      pixels.push(0);
      pixels.push(this._getIndexValue(i));
      pixels.push(0);
    }
    return { data: pixels };
  }

  scaled() {
    return this.without_text();
  }
}
