import { logIfDebug, warnIfDebug, warnOnceIfDebug } from 'utils/log';
import { getElement } from 'utils/dom';
import config from 'Ractive/config/config';
import Fragment from 'view/Fragment';
import Hook from 'events/Hook';
import HookQueue from 'events/HookQueue';
import Ractive from '../Ractive';

let configHook = new Hook( 'config' );
let initHook = new HookQueue( 'init' );

export default function initialise ( ractive, userOptions, options ) {
	Object.keys( ractive.viewmodel.computations ).forEach( key => {
		ractive.viewmodel.computations[ key ].init();
	});

	// init config from Parent and options
	config.init( ractive.constructor, ractive, userOptions );

	configHook.fire( ractive );
	initHook.begin( ractive );

	// Render virtual DOM
	if ( ractive.template ) { // TODO ractive.template is always truthy, because of the defaults...
		let cssIds;

		if ( options.cssIds || ractive.cssId ) {
			cssIds = options.cssIds ? options.cssIds.slice() : [];

			if ( ractive.cssId ) {
				cssIds.push( ractive.cssId );
			}
		}

		ractive.fragment = new Fragment({
			owner: ractive,
			template: ractive.template,
			cssIds,
			indexRefs: options.indexRefs || {},
			keyRefs: options.keyRefs || {}
		});
	}

	initHook.end( ractive );

	// TODO initHook moved to before binding... will this break
	// this.findComponent inside oninit? Is that a problem?
	// Should be onrender anyway, right?
	if ( ractive.fragment ) {
		ractive.fragment.bind( ractive.viewmodel );

		// render automatically ( if `el` is specified )
		const el = getElement( ractive.el );
		if ( el ) {
			let promise = ractive.render( el, ractive.append );

			if ( Ractive.DEBUG_PROMISES ) {
				promise.catch( err => {
					warnOnceIfDebug( 'Promise debugging is enabled, to help solve errors that happen asynchronously. Some browsers will log unhandled promise rejections, in which case you can safely disable promise debugging:\n  Ractive.DEBUG_PROMISES = false;' );
					warnIfDebug( 'An error happened during rendering', { ractive });
					err.stack && logIfDebug( err.stack );

					throw err;
				});
			}
		}
	}
}

@@ -508,24 +508,44 @@
  key =%3E %7B%0A%09%09
+const computation = 
 ractive.view
@@ -569,16 +569,146 @@
 s%5B key %5D
+;%0A%09%09if ( ractive.viewmodel.value.hasOwnProperty( key ) ) %7B%0A%09%09%09computation.set( ractive.viewmodel.value%5B key %5D );%0A%09%09%7D%0A%09%09computation
 .init();

initialise computations with existing values where appropriate