/**
 * @fileoverview Utility module for blocks.js
 * 
 * @module games.semaforo.blocks.blocks
 */

"use strict";

import * as Blockly from "blockly/core";
import { javascriptGenerator } from "blockly/javascript";

const HUE_SEMAFORO = "#2196F3";
const HUE_PEDRESTRE = "#E072A4";
const HUE_CONTROLE = "#FF9800";
const HUE_MIDIA = "#26979f";
const HUE_TEMPO = "#9C27B0";

export const registerBlocks = () => {
  defineBlocks();
  defineGenerators();
};

/**
 * Registra todos os blocos personalizados do Semáforo no Blockly.
 * Executa tanto a definição dos blocos quanto a definição dos geradores de código.
 * @returns {void}
 */

export const generateDynamicToolbox = (allowedBlocks = []) => {
  const filteredToolbox = JSON.parse(JSON.stringify(semaforoToolbox));

  filteredToolbox.contents.forEach((category) => {
    if (category.contents) {
      category.contents = category.contents.filter(
        (block) => block.type && allowedBlocks.includes(block.type),
      );
    }
  });

  filteredToolbox.contents = filteredToolbox.contents.filter(
    (category) => category.contents && category.contents.length > 0,
  );

  return filteredToolbox;
};

/**
 * Gera uma toolbox dinâmica filtrada pelos blocos permitidos para a fase.
 * @param {string[]} [allowedBlocks=[]] - Lista de tipos de blocos permitidos.
 * @returns {Object} Estrutura JSON compatível com a toolbox do Blockly.
 */

/**
 * Define a coleção de blocos do semáforo (chamada internamente por `registerBlocks`).
 * Blocos definidos: `mudar_semaforo`, `mudar_semaforo_pedestre`, `piscar_luz_pedestre`,
 * `tocar_som`, `parar_som`, `aguardar_segundos`, `repetir`.
 * @private
 * @returns {void}
 */
const defineBlocks = () => {
  Blockly.Blocks["mudar_semaforo"] = {
    init: function () {
      this.jsonInit({
        message0: "mudar semáforo para %1",
        args0: [
          {
            type: "field_dropdown",
            name: "COR",
            options: [
              ["🟢 verde", "verde"],
              ["🟡 amarelo", "amarelo"],
              ["🔴 vermelho", "vermelho"],
            ],
          },
        ],
        previousStatement: null,
        nextStatement: null,
        colour: HUE_SEMAFORO,
        tooltip: "Muda a cor do semáforo dos carros.",
      });
    },
  };

  Blockly.Blocks["mudar_semaforo_pedestre"] = {
    init: function () {
      this.jsonInit({
        message0: "mudar semáforo de pedestre para %1",
        args0: [
          {
            type: "field_dropdown",
            name: "COR",
            options: [
              ["🟢 verde", "verde"],
              ["🔴 vermelho", "vermelho"],
            ],
          },
        ],
        previousStatement: null,
        nextStatement: null,
        colour: HUE_PEDRESTRE,
        tooltip: "Muda a cor do semáforo de pedestre.",
      });
    },
  };

  Blockly.Blocks["piscar_luz_pedestre"] = {
    init: function () {
      this.jsonInit({
        message0: "piscar luz do pedestre %1 por %2 segundos",
        args0: [
          {
            type: "field_dropdown",
            name: "COR",
            options: [
              ["🟢 verde", "verde"],
              ["🔴 vermelho", "vermelho"],
            ],
          },
          {
            type: "field_number",
            name: "TEMPO",
            value: 5,
            min: 0,
            max: 60,
          },
        ],
        previousStatement: null,
        nextStatement: null,
        colour: HUE_PEDRESTRE,
        tooltip: "Faz a luz do semáforo de pedestre piscar na cor escolhida.",
      });
    },
  };

  Blockly.Blocks["tocar_som"] = {
    init: function () {
      this.jsonInit({
        message0: "🔈 tocar som %1",
        args0: [
          {
            type: "field_dropdown",
            name: "SOM",
            options: [["🚦 beep semáforo", "beep_semaforo"]],
          },
        ],
        previousStatement: null,
        nextStatement: null,
        colour: HUE_MIDIA,
        tooltip: "Toca um som do jogo.",
      });
    },
  };

  Blockly.Blocks["parar_som"] = {
    init: function () {
      this.jsonInit({
        message0: "🔇parar som %1",
        args0: [
          {
            type: "field_dropdown",
            name: "SOM",
            options: [["🚦 beep semáforo", "beep_semaforo"]],
          },
        ],
        previousStatement: null,
        nextStatement: null,
        colour: HUE_MIDIA,
        tooltip: "Para um som do jogo.",
      });
    },
  };

  Blockly.Blocks["aguardar_segundos"] = {
    init: function () {
      this.jsonInit({
        message0: "aguardar %1 segundos",
        args0: [
          {
            type: "field_number",
            name: "TEMPO",
            value: 1,
            min: 0,
            max: 60,
          },
        ],
        previousStatement: null,
        nextStatement: null,
        colour: "#9C27B0",
        tooltip: "Espera o tempo definido antes de continuar.",
      });
    },
  };

  Blockly.Blocks["repetir"] = {
    init: function () {
      this.appendDummyInput().appendField("enquanto estiver em execução");
      this.appendStatementInput("DO").setCheck(null).appendField("faça");
      this.setPreviousStatement(true, null);
      this.setNextStatement(true, null);
      this.setColour("#FF9800");
      this.setTooltip("Repete as ações enquanto problema estiver em execução");
      this.setHelpUrl("");
    },
  };
};

/**
 * Define os geradores JavaScript associados aos blocos do semáforo.
 * Configura prefixos de highlight e tem geradores para cada bloco de ação.
 * @private
 * @returns {void}
 */
const defineGenerators = () => {
  javascriptGenerator.STATEMENT_PREFIX = "highlightBlock(%1);\n";
  javascriptGenerator.addReservedWords("highlightBlock");

  javascriptGenerator.forBlock["mudar_semaforo"] = (block) => {
    const cor = block.getFieldValue("COR");
    return `mudarSemaforo('${cor}');\n`;
  };

  javascriptGenerator.forBlock["mudar_semaforo_pedestre"] = (block) => {
    const cor = block.getFieldValue("COR");
    return `mudarSemaforoPedestre('${cor}');\n`;
  };

  javascriptGenerator.forBlock["aguardar_segundos"] = (block) => {
    const tempo = Number(block.getFieldValue("TEMPO"));
    return `aguardarSegundos(${tempo});\n`;
  };

  javascriptGenerator.forBlock["repetir"] = (block) => {
    const statements = javascriptGenerator.statementToCode(block, "DO");
    return `while(true) {\n${statements}};\n`;
  };

  javascriptGenerator.forBlock["piscar_luz_pedestre"] = (block) => {
    const cor = block.getFieldValue("COR");
    const tempo = Number(block.getFieldValue("TEMPO"));
    return `piscarLuzPedestre('${cor}', ${tempo});\n`;
  };

  javascriptGenerator.forBlock["tocar_som"] = (block) => {
    const som = block.getFieldValue("SOM");
    return `tocarSom('${som}');\n`;
  };

  javascriptGenerator.forBlock["parar_som"] = (block) => {
    const som = block.getFieldValue("SOM");
    return `pararSom('${som}');\n`;
  };
};

export const semaforoToolbox = {
  kind: "categoryToolbox",
  contents: [
    {
      kind: "category",
      name: "Repetição",
      colour: HUE_CONTROLE,
      contents: [{ kind: "block", type: "repetir" }],
      cssConfig: {
        container: "repeticao",
      },
    },
    {
      kind: "category",
      name: "Tempo",
      colour: HUE_TEMPO,
      contents: [{ kind: "block", type: "aguardar_segundos" }],
      cssConfig: {
        container: "aguardar",
      },
    },
    {
      kind: "category",
      name: "Semáforo Carros",
      colour: HUE_SEMAFORO,
      contents: [{ kind: "block", type: "mudar_semaforo" }],
    },
    {
      kind: "category",
      name: "Semáforo Pedestre",
      colour: HUE_PEDRESTRE,
      contents: [
        { kind: "block", type: "mudar_semaforo_pedestre" },
        { kind: "block", type: "piscar_luz_pedestre" },
      ],
    },
    {
      kind: "category",
      name: "Multimídia",
      colour: HUE_MIDIA,
      contents: [
        { kind: "block", type: "tocar_som" },
        { kind: "block", type: "parar_som" },
      ],
    },
  ],
};

/**
 * Toolbox padrão do semáforo usado como base para `generateDynamicToolbox`.
 * @type {Object}
 */
