import {
  buildPlayerAvatars,
  drawAllNewCells,
  drawBackgrounds,
  drawBackgroundTopElements,
  drawFlags,
  drawNewAdditionalStuff,
} from './western-world.utils';
import { ORIGINAL_WESTERN_WORLD_HEIGHT, ORIGINAL_WESTERN_WORLD_WIDTH } from './western-world.utils.constants';
import { shouldRedraw } from './western-world.utils.helpers';

const template = document.createElement('template');
template.innerHTML = `
    <style>
      :host {
        display: block;
        position: relative;
      }
      canvas {
        width: 100%;
        top: 0;
        left: 0;
        transition: filter 0.5s;
      }
      .flags {
        position: absolute;
        top: 0;
        left: 0;
      }
    </style>

    <canvas class="constant"></canvas>
    <canvas class="flags"></canvas>
  `;

class WesternWorld extends window['WesternBaseHTMLElement'] {
  // Inputs:
  // game;
  // allCells;
  // myIdKey;
  // playersIconMap;
  // showWesternBackground;
  // SIZE_X_QUALITY;
  // PADDING_LEFT;
  // PADDING_RIGHT;
  // PADDING_TOP;
  // PADDING_BOTTOM;
  // language;

  // Outputs:
  // allImagesLoaded

  constructor() {
    super();
    this._shadowRoot = this.attachShadow({ mode: 'open' });
    this._shadowRoot.appendChild(template.content.cloneNode(true));
    this.$canvasConstant = this._shadowRoot.querySelector('canvas.constant');
    this.$canvasFlags = this._shadowRoot.querySelector('canvas.flags');
    this.state = {
      language: null,
      showWesternBackground: null,
      allCells: null,
      game: null,
    };
    this.detectChangesInprogress = false;
  }

  areAllInitialized() {
    return (
      this.state.language && this.state.showWesternBackground !== undefined && this.state.game && this.state.allCells
    );
  }

  set language(value) {
    this.setState('language', value);
  }

  set showWesternBackground(value) {
    this.setState('showWesternBackground', value);
  }

  set allCells(value) {
    this.setState('allCells', value);
  }

  set game(value) {
    if (shouldRedraw(value, this.state.game)) {
      this.setState('game', value);
      return;
    }
    // if game object doesn't effect western-world canvas don't need setState that rerenders, just save game to the state without rerendering;
    this.state.game = value;
  }

  render({ changes }) {
    window['western-world-utils']
      .fetchImages({ language: this.state.language, allCells: this.state.allCells })
      .then(() =>
        this.dispatchEvent(new CustomEvent('allImagesLoaded', { detail: window.cachedImages[this.state.language] }))
      )
      .then(() => buildPlayerAvatars({ avatars: this.playersIconMap, language: this.state.language }))
      .then(() => {
        if (changes.language || changes.showWesternBackground) {
          this.drawWesternWorld();
          this.dispatchEvent(new CustomEvent('finishedRendering'));
        }
        this.drawFlagsCanvas();
      });
  }

  drawWesternWorld() {
    // Background images should start before western-world starts and it should end after it ends
    // to have posibility to add stuff in the left and right free areas where no weestern space.
    // I guess 1000 additional pixels would be enough;
    const FREE_AREA = 333.33 * this.SIZE_X_QUALITY;
    const BACKGROUND_X = this.PADDING_LEFT - FREE_AREA;
    const BACKGROUND_Y = this.PADDING_TOP - FREE_AREA;
    const BACKGROUND_WIDTH = ORIGINAL_WESTERN_WORLD_WIDTH * this.SIZE_X_QUALITY + FREE_AREA * 2;
    const BACKGROUND_HEIGHT = ORIGINAL_WESTERN_WORLD_WIDTH * this.SIZE_X_QUALITY + FREE_AREA * 2;

    this.$canvasConstant.width =
      ORIGINAL_WESTERN_WORLD_WIDTH * this.SIZE_X_QUALITY + this.PADDING_LEFT + this.PADDING_RIGHT;
    this.$canvasConstant.height =
      ORIGINAL_WESTERN_WORLD_HEIGHT * this.SIZE_X_QUALITY + this.PADDING_TOP + this.PADDING_BOTTOM;
    const ctx = this.$canvasConstant.getContext('2d');

    if (this.state.showWesternBackground) {
      this.$canvasConstant.style.background = 'white';
      drawBackgrounds({
        ctx,
        BACKGROUND_X,
        BACKGROUND_Y,
        BACKGROUND_WIDTH,
        BACKGROUND_HEIGHT,
        language: this.state.language,
      });
    } else {
      this.$canvasConstant.style.background = 'transparent';
    }

    // append all new images;
    drawAllNewCells({
      allCells: this.state.allCells,
      ctx,
      SIZE_X_QUALITY: this.SIZE_X_QUALITY,
      PADDING_LEFT: this.PADDING_LEFT,
      PADDING_TOP: this.PADDING_TOP,
      language: this.state.language,
    });

    if (this.state.showWesternBackground) {
      drawBackgroundTopElements({
        ctx,
        BACKGROUND_X,
        BACKGROUND_Y,
        BACKGROUND_WIDTH,
        BACKGROUND_HEIGHT,
        language: this.state.language,
      });
    }

    drawNewAdditionalStuff({
      ctx,
      SIZE_X_QUALITY: this.SIZE_X_QUALITY,
      PADDING_LEFT: this.PADDING_LEFT,
      PADDING_TOP: this.PADDING_TOP,
      language: this.state.language,
    });
  }

  drawFlagsCanvas() {
    const ctxFlags = this.$canvasFlags.getContext('2d');
    this.$canvasFlags.width =
      ORIGINAL_WESTERN_WORLD_WIDTH * this.SIZE_X_QUALITY + this.PADDING_LEFT + this.PADDING_RIGHT;
    this.$canvasFlags.height =
      ORIGINAL_WESTERN_WORLD_HEIGHT * this.SIZE_X_QUALITY + this.PADDING_TOP + this.PADDING_BOTTOM;
    // draw flags;
    drawFlags({
      allCells: this.state.allCells,
      ctx: ctxFlags,
      game: this.state.game,
      myIdKey: this.myIdKey,
      SIZE_X_QUALITY: this.SIZE_X_QUALITY,
      PADDING_LEFT: this.PADDING_LEFT,
      PADDING_TOP: this.PADDING_TOP,
      language: this.state.language,
    });
  }
}

window.customElements.define('western-world', WesternWorld);
