/**
 * Market Data Generators Definitions
 *
 * This file contains generator functions for each block defined in
 * market_data_blocks.js. Each generator translates a Blockly block into a JSON
 * object representing market data retrieval operations.
 */

export function defineMarketDataGenerators() {

    // Ensure the base generator is initialized and 'createOperationObject' is available
    if (!Blockly.JSON || !Blockly.JSON.createOperationObject) {
        console.error("Blockly.JSON or createOperationObject not initialized. Please ensure 'json_base_generator.js' is loaded first.");
        return;
    }

    /**
     * Helper Function: processSourceInput
     * Processes the 'source' input, ensuring it is a valid source block and returning its value if connected.
     *
     * @param {Blockly.Block} block - The block containing the 'source' input.
     * @returns {Object} - The source object or a default empty object if validation fails.
     */
    function processSourceInput(block) {
        const sourceBlock = block.getInputTargetBlock('source');
        if (sourceBlock && sourceBlock.type === 'source') {
            return Blockly.JSON.blockToCode(sourceBlock); // Process source configuration
        }

        console.warn(`Invalid or missing source block connected to 'source' input of '${block.type}' block. Using default configuration.`);
        return {}; // Default empty object if validation fails
    }

    /**
     * General function to generate market data blocks, handling additional values.
     * Uses extractValues to pull optional extra values connected to 'source'.
     */
    function generateMarketDataBlock(block, operationType) {
        // Process the 'source' input (optional) and additional values
        const source = processSourceInput(block);
        const operationObject = Blockly.JSON.createOperationObject(operationType, { source: source.values ? source.values[0] : source });

        // Initialize output values array
        const outputValues = [operationObject];

        // Add the remaining values from source if it contains a dynamic_value structure
        if (source?.type === 'dynamic_value' && Array.isArray(source.values)) {
            outputValues.push(...source.values.slice(1));
        }

        // Use extractValues to capture additional values beyond the primary source
        const additionalValues = Blockly.JSON.extractValues(block, 'source'); // Extract additional values if any
        if (additionalValues.length > 0) {
            outputValues.push(...additionalValues);
        }

        return {
            type: 'dynamic_value',
            values: outputValues
        };
    }


    /**
     * Generator for 'current_price' Block
     */
    Blockly.JSON['current_price'] = function(block) {
        return generateMarketDataBlock(block, 'current_price');
    };

    /**
     * Generator for 'bid_price' Block
     */
    Blockly.JSON['bid_price'] = function(block) {
        return generateMarketDataBlock(block, 'bid_price');
    };

    /**
     * Generator for 'ask_price' Block
     */
    Blockly.JSON['ask_price'] = function(block) {
        return generateMarketDataBlock(block, 'ask_price');
    };

    /**
     * Generator for 'last_candle_value' Block
     */
    Blockly.JSON['last_candle_value'] = function(block) {
        const source = processSourceInput(block);
        const candlePart = block.getFieldValue('candle_part') || 'close';
        const validCandleParts = ['open', 'high', 'low', 'close'];
        const validatedCandlePart = validCandleParts.includes(candlePart) ? candlePart : 'close';

        const operationObject = Blockly.JSON.createOperationObject('last_candle_value', {
            source,
            candle_part: validatedCandlePart
        });

        const outputValues = [operationObject];
        const additionalValues = Blockly.JSON.extractValues(block, 'source'); // Use extractValues for any additional values
        if (additionalValues.length > 0) {
            outputValues.push(...additionalValues);
        }

        return {
            type: 'dynamic_value',
            values: outputValues
        };
    };

    /**
     * Generator for 'source' Block
     */
    Blockly.JSON['source'] = function(block) {
        const timeFrame = block.getFieldValue('TF') || '1m';
        const exchange = block.getFieldValue('EXC') || 'Binance';
        const symbol = block.getFieldValue('SYM') || 'BTCUSDT';

        // Create source object
        const operationObject = Blockly.JSON.createOperationObject('source', {
            time_frame: timeFrame,
            exchange: exchange,
            symbol: symbol});

         // Prepare output, handling any additional values
        const outputValues = [operationObject];
        const valuesArray = Blockly.JSON.processValuesInput(block);
        if (valuesArray.length > 0) {
            outputValues.push(...valuesArray);
        }

        return {
            type: 'dynamic_value',
            values: outputValues
        };
    };
}
