class Mapa {
  celdas = [];
  barcos = [];
  barcoSeleccionado;

  constructor(canvas, size, scale) {
    this.canvas = canvas;
    this.canvas.width = size;
    this.canvas.height = size;
    this.width = size / scale;
    this.height = size / scale;
    this.ctx = this.canvas.getContext("2d");
    this.scale = scale;
    this.ctx.scale(this.scale, this.scale);

    this.casillaSize = 64;
    this.numFilas = 10;
    this.numColumnas = 10;

    this.inicializarCeldas();

    canvas.addEventListener("click", this.getPosClick);
    canvas.addEventListener("contextmenu", this.giraBarcoSeleccionado);
    canvas.addEventListener("mousemove", this.mueveBarcoSeleccionado);
    document.addEventListener("keydown", this.handleKeyDown);
  }

  inicializarCeldas() {
    for (let i = 0; i < this.numFilas; i++) {
      this.celdas[i] = new Array(this.numColumnas).fill(0);
    }
  }

  setBarcos(barcos) {
    const barcosArray = Array.isArray(barcos) ? barcos : [barcos];
    for (const barco of barcosArray) {
      barco.seleccionado = false;
      const incFila = barco.orientacion === "VERTICAL" ? 1 : 0;
      const incColumna = barco.orientacion === "HORIZONTAL" ? 1 : 0;
      for (let i = 0; i < barco.longitud; i++) {
        const fila = barco.y + i * incFila;
        const columna = barco.x + i * incColumna;
        this.celdas[fila][columna] = barco.longitud;
      }
    }
    this.barcos.push(...barcosArray);
  }

  calcularCoordenadas(event) {
    const rect = this.canvas.getBoundingClientRect();
    const x = Math.floor(
      (event.clientX - rect.left) / (this.casillaSize * this.scale)
    );
    const y = Math.floor(
      (event.clientY - rect.top) / (this.casillaSize * this.scale)
    );
    return { x, y };
  }

  //Acuerdate!!!! funcion de flecha en los callBack para no tener problemas con el contexto this
  handleKeyDown = (event) => {
    const canvasFocused = document.activeElement === this.canvas;
    if (canvasFocused && event.key === "Escape" && this.barcoSeleccionado) {
      this.barcoSeleccionado.restoreIniPos();
      this.posicionaBarcoSeleccionado();
    }
  };
  //Acuerdate!!!! funcion de flecha en los callBack para no tener problemas con el contexto this
  giraBarcoSeleccionado = (event) => {
    event.preventDefault();
    if (this.barcoSeleccionado) {
      if (
        this.barcoSeleccionado.x + this.barcoSeleccionado.longitud <=
          this.numColumnas &&
        this.barcoSeleccionado.y + this.barcoSeleccionado.longitud <=
          this.numFilas
      ) {
        this.barcoSeleccionado.giraBarco();
      }
    }
  };
  //Acuerdate!!!! funcion de flecha en los callBack para no tener problemas con el contexto this
  getPosClick = (event) => {
    const { x, y } = this.calcularCoordenadas(event);
    if (!this.barcoSeleccionado) {
      const index = this.barcos.findIndex((barco) => barco.clickado(x, y));
      if (index != -1) this.seleccionaBarco(index);
    } else {
      this.posicionaBarcoSeleccionado();
    }
  };

  seleccionaBarco(index_barco) {
    this.barcoSeleccionado = this.barcos[index_barco];
    this.barcoSeleccionado.seleccionado = true;
    this.barcoSeleccionado.saveIniPos();
    this.barcos.splice(index_barco, 1);
    const incFila = this.barcoSeleccionado.orientacion === "VERTICAL" ? 1 : 0;
    const incColumna =
      this.barcoSeleccionado.orientacion === "HORIZONTAL" ? 1 : 0;
    for (let i = 0; i < this.barcoSeleccionado.longitud; i++) {
      const fila = this.barcoSeleccionado.y + i * incFila;
      const columna = this.barcoSeleccionado.x + i * incColumna;
      this.celdas[fila][columna] = 0;
    }
  }
  //Acuerdate!!!! funcion de flecha en los callBack para no tener problemas con el contexto this
  mueveBarcoSeleccionado = (event) => {
    if (this.barcoSeleccionado) {
      const { x, y } = this.calcularCoordenadas(event);
      if (!this.colisionBorde(x, y)) this.barcoSeleccionado.setXY(x, y);
    }
  };
  posicionaBarcoSeleccionado() {
    this.setBarcos(this.barcoSeleccionado);
    this.barcoSeleccionado = null;
  }
  colisionBorde(x, y) {
    const barco = this.barcoSeleccionado;
    const longitud = barco.longitud;
    const orientacion = barco.orientacion;
    return orientacion === "VERTICAL"
      ? x < 0 || x >= this.numColumnas || y < 0 || y + longitud > this.numFilas
      : x < 0 || x + longitud > this.numColumnas || y < 0 || y > this.numFilas;
  }

  draw() {
    this.ctx.clearRect(0, 0, this.width, this.height);
    this.barcos.forEach((barco) => {
      barco.draw(this.ctx);
    });

    if (this.barcoSeleccionado) this.barcoSeleccionado.draw(this.ctx);

    this.ctx.beginPath();
    for (let i = 0; i <= this.numFilas; i++) {
      const y = i * this.casillaSize;
      this.ctx.moveTo(0, y);
      this.ctx.lineTo(this.casillaSize * this.numColumnas, y);
    }
    for (let i = 0; i <= this.numColumnas; i++) {
      const x = i * this.casillaSize;
      this.ctx.moveTo(x, 0);
      this.ctx.lineTo(x, this.casillaSize * this.numFilas);
    }
    this.ctx.strokeStyle = "#15ff0040";
    this.ctx.stroke();
  }
}

export default Mapa;
