/**
 * @fileoverview Helpers para configuração de geradores Blockly
 * @module blockly.generator
 */

import { javascriptGenerator } from "blockly/javascript";

/**
 * Configura o gerador JavaScript com prefixo de highlight.
 * Deve ser chamado no início de `defineGenerators()` em cada jogo.
 * 
 * @param {Object} [generator=javascriptGenerator] - Instância do gerador
 * @returns {void}
 * 
 * @example
 * const defineGenerators = () => {
 *   configurarGerador();
 *   // ... resto dos geradores
 * };
 */
export const configurarGerador = (generator = javascriptGenerator) => {
  generator.STATEMENT_PREFIX = "highlightBlock(%1);\n";
  generator.addReservedWords("highlightBlock");
};

/**
 * Cria gerador para expressão (retorna valor).
 * Usa ORDER_ATOMIC por padrão, ideal para variáveis e constantes.
 * Use ORDER_FUNCTION_CALL para chamadas de função.
 * 
 * @param {string} blockId - ID do bloco
 * @param {string} codigo - Código JavaScript a retornar
 * @param {number} [precedencia] - Precedência da expressão (opcional)
 * @returns {void}
 * 
 * @example
 * // Variável
 * gerarExpressao("robo_passos_get", "passos");
 * 
 * // Função
 * gerarExpressao("robo_sensor", "aindaTemSujeira()", javascriptGenerator.ORDER_FUNCTION_CALL);
 */
export const gerarExpressao = (blockId, codigo, precedencia = null) => {
  const order = precedencia ?? javascriptGenerator.ORDER_ATOMIC;
  javascriptGenerator.forBlock[blockId] = () => [codigo, order];
};

/**
 * Cria gerador para statement (comando sem retorno).
 * Gera código do tipo: funcao();\n
 * 
 * @param {string} blockId - ID do bloco
 * @param {string} funcao - Nome da função JavaScript
 * @returns {void}
 * 
 * @example
 * gerarStatement("robo_mover", "mover");
 * // Gera: mover();\n
 */
export const gerarStatement = (blockId, funcao) => {
  javascriptGenerator.forBlock[blockId] = () => `${funcao}();\n`;
};

/**
 * Cria gerador para statement com código inline.
 * Útil para operações simples sem função externa.
 * 
 * @param {string} blockId - ID do bloco
 * @param {string} codigo - Código JavaScript completo
 * @returns {void}
 * 
 * @example
 * gerarStatementInline("robo_passos_change", "passos = passos + 1");
 * // Gera: passos = passos + 1;\n
 */
export const gerarStatementInline = (blockId, codigo) => {
  javascriptGenerator.forBlock[blockId] = () => `${codigo};\n`;
};

/**
 * Cria gerador para statement que usa valor de campo dropdown.
 * 
 * @param {string} blockId - ID do bloco
 * @param {string} funcao - Nome da função a chamar
 * @param {string} nomeCampo - Nome do campo dropdown
 * @returns {void}
 * 
 * @example
 * gerarStatementComCampo("robo_virar", "virar", "DIRECAO");
 * // Gera: virar('DIREITA');\n
 */
export const gerarStatementComCampo = (blockId, funcao, nomeCampo) => {
  javascriptGenerator.forBlock[blockId] = function (block) {
    return `${funcao}('${block.getFieldValue(nomeCampo)}');\n`;
  };
};

/**
 * Cria gerador para expressão que usa valor de campo dropdown.
 * 
 * @param {string} blockId - ID do bloco
 * @param {string} funcao - Nome da função a chamar
 * @param {string} nomeCampo - Nome do campo dropdown
 * @param {number} precedencia - Precedência do operador
 * @returns {void}
 * 
 * @example
 * gerarExpressaoComCampo("robo_bloqueado", "caminhoBloqueado", "SENTIDO", 
 *   javascriptGenerator.ORDER_FUNCTION_CALL);
 * // Gera: ['caminhoBloqueado(\'FRENTE\')', ORDER_FUNCTION_CALL]
 */
export const gerarExpressaoComCampo = (blockId, funcao, nomeCampo, precedencia) => {
  javascriptGenerator.forBlock[blockId] = function (block) {
    return [`${funcao}('${block.getFieldValue(nomeCampo)}')`, precedencia];
  };
};

/**
 * Cria gerador para statement que usa valor de value input.
 * 
 * @param {string} blockId - ID do bloco
 * @param {string} nomeInput - Nome do value input
 * @param {Function} template - Função que recebe o valor e retorna código
 * @returns {void}
 * 
 * @example
 * gerarStatementComValor("robo_passos_set", "VALOR", 
 *   (valor) => `var passos = ${valor}`);
 * // Gera: var passos = 42;\n
 */
export const gerarStatementComValor = (blockId, nomeInput, template) => {
  javascriptGenerator.forBlock[blockId] = function (block) {
    const valor = javascriptGenerator.valueToCode(
      block, 
      nomeInput, 
      javascriptGenerator.ORDER_ASSIGNMENT
    ) || "0";
    return `${template(valor)};\n`;
  };
};