import deindent from '../utils/deindent.js';
import counter from '../utils/counter.js';

// collect all the conditions and blocks in the if/elseif/else chain
function generateBlock ( generator, node, name ) {
	// walk the children here
	generator.push({
		useAnchor: true,
		name,
		target: 'target',
		localElementDepth: 0,

		initStatements: [],
		mountStatements: [],
		updateStatements: [],
		teardownStatements: [],

		counter: counter()
	});
	node.children.forEach( generator.visit );
	generator.addRenderer( generator.current );
	generator.pop();
	// unset the children, to avoid them being visited again
	node.children = [];
}

function getConditionsAndBlocks ( generator, node, _name, i = 0 ) {
	generator.addSourcemapLocations( node.expression );
	const name = `${_name}_${i}`;

	const conditionsAndBlocks = [{
		condition: generator.contextualise( node.expression ).snippet,
		block: name
	}];
	generateBlock( generator, node, name );

	if ( node.else && node.else.children.length === 1 &&
		node.else.children[0].type === 'IfBlock' ) {
		conditionsAndBlocks.push(
			...getConditionsAndBlocks( generator, node.else.children[0], _name, i + 1 ) );
	} else {
		const name = `${_name}_${i + 1}`;
		conditionsAndBlocks.push({
			condition: null,
			block: node.else ? name : null,
		});
		if (node.else) {
			generateBlock( generator, node.else, name );
		}
	}
	return conditionsAndBlocks;
}

export default {
	enter ( generator, node ) {
		const i = generator.counters.if++;

		const { params } = generator.current;
		const name = `ifBlock_${i}`;
		const getBlock = `getBlock_${i}`;
		const currentBlock = `currentBlock_${i}`;

		const isToplevel = generator.current.localElementDepth === 0;
		const conditionsAndBlocks = getConditionsAndBlocks( generator, node, `renderIfBlock_${i}` );

		const anchor = generator.createAnchor( name, `#if ${generator.source.slice( node.expression.start, node.expression.end )}` );

		generator.current.initStatements.push( deindent`
			function ${getBlock} ( ${params} ) {
				${conditionsAndBlocks.map( ({ condition, block }) => {
					return `${condition ? `if ( ${condition} ) ` : ''}return ${block};`;
				} ).join( '\n' )}
			}

			var ${currentBlock} = ${getBlock}( ${params} );
			var ${name} = ${currentBlock} && ${currentBlock}( ${params}, component );
		` );

		const mountStatement = `if ( ${name} ) ${name}.mount( ${anchor}.parentNode, ${anchor} );`;
		if ( isToplevel ) {
			generator.current.mountStatements.push( mountStatement );
		} else {
			generator.current.initStatements.push( mountStatement );
		}

		generator.current.updateStatements.push( deindent`
			var _${currentBlock} = ${currentBlock};
			${currentBlock} = ${getBlock}( ${params} );
			if ( _${currentBlock} === ${currentBlock} && ${name}) {
				${name}.update( changed, ${params} );
			} else {
				if ( ${name} ) ${name}.teardown( true );
				${name} = ${currentBlock} && ${currentBlock}( ${params}, component );
				if ( ${name} ) ${name}.mount( ${anchor}.parentNode, ${anchor} );
			}
		` );

		generator.current.teardownStatements.push( deindent`
			if ( ${name} ) ${name}.teardown( ${isToplevel ? 'detach' : 'false'} );
		` );
	}
};