
export default function *() {

	// Get current store from state or else set a default if it exists
	var store = this.getState('Builder', {
		initializing: false,
		initialized: false,
		selectedBoard: 1,
		selectedPort: '',
		compilerflasher: null,
		boards_list: [],
		ports_list: [],
		code: '',
		files: {},
		verified: false,
		verifying: false,
		compiling: false,
		compiled: false,
		flashing: false,
		flashed: false,
		status: 'initializing',
		serialMonitor: false
	});

	this.on('store.Builder.initialize', function *() {

		var store = this.getState('Builder');
		if (this.isBrowser && !store.compilerflasher && !store.initializing) {
			store.initializing = true;

			var $script = require('scriptjs');
			var self = this;
			$script('//codebender.cc/embed/compilerflasher.js', function() {

					store.compilerflasher = compilerflasher = new compilerflasher(function() {
						return store.files;
					});

					compilerflasher.on('plugin_notification', function(msg) {
						console.log(msg);
					});

					compilerflasher.on('plugin_running', function() {
						store.boards_list = compilerflasher.boards_list;
						store.initialized = true;
						store.status = 'ready';

						self.dispatch('store.Builder', 'change');

						// Check whether codebender plugin is ready or not
						var cur = '';
						var portDetector = setInterval(function() {

							// Detected new ports
							if (cur != compilerflasher.pluginHandler.oldPorts) {
								cur = compilerflasher.pluginHandler.oldPorts;

								if (!store.ports_list.length)
									store.serialMonitor = true;

								store.ports_list = compilerflasher.pluginHandler.currentPorts;

								// Still no available port
								if (!store.ports_list.length) {
									store.serialMonitor = false;
								} else {
									// Try to select the correct ports
									$('#cb_cf_ports').prop('selectedIndex', 0).change();
									store.selectedPort = store.ports_list[0];
									store.ports_list.forEach(function(port, index) {
										if (port.indexOf('usbmodem') == -1)
											return;

										$('#cb_cf_ports').prop('selectedIndex', index).change();
										store.selectedPort = port;
									});
								}

								self.dispatch('store.Builder', 'change');
							}

						}, 500);
					});

					compilerflasher.on('pre_verify', function() {
						console.log('Verifying ...');
						store.verified = false;
						store.verifying = true;
						self.dispatch('store.Builder', 'change');
					});

					compilerflasher.on('verification_failed', function(message) {
						store.verifying = false;
						store.status = 'verification-failed';
						console.log('VERIFICATION FAILED')
						self.dispatch('store.Builder', 'change');
					});

					compilerflasher.on('verification_succeed', function(binary_size) {

						console.log('COMPILED SUCCESSFULY');

						store.verifying = false;
						store.verified = true;

						self.dispatch('store.Builder', 'change');
					});

					compilerflasher.on('pre_flash', function(size) {
						store.compiled = false;
						store.compiling = true;
						console.log('PRE FLASH');
						self.dispatch('store.Builder', 'change');
					});

					compilerflasher.on('mid_flash', function(size) {
						store.compiling = false;
						store.compiled = true;
						store.flashing = true;
						store.flashed = false;
						console.log('COMPILED');
						self.dispatch('store.Builder', 'change');
					});

					compilerflasher.on('flash_failed', function(message) {
						store.flashing = false;
						store.flashed = false;
						console.log('FLASH_FAILED', message);
						if (message.indexOf('Could not connect to your device') != -1) {
							store.status = 'flash-failed-cannot-connect-device';
						} else {
							store.status = 'flash-failed';
						}
/*
						setTimeout(function() {
							store.serialMinitor = true;
							self.dispatch('store.Builder', 'change');
						}, 1000);
*/
						self.dispatch('store.Builder', 'change');
					});

					compilerflasher.on('flash_succeed', function(message) {
						store.flashing = false;
						store.flashed = true;
						console.log('FLASH_SUCCEED');
						store.status = 'flash-succeed';
/*
						setTimeout(function() {
							store.serialMinitor = true;
							self.dispatch('store.Builder', 'change');
						}, 1000);
*/
						self.dispatch('store.Builder', 'change');
					});

			});
		}
	});

	this.on('store.Builder.selectPort', function *(port) {

		var store = this.getState('Builder');

		// No changes
		if (store.selectedPort == port)
			return;

		// Selecting port
		$('#cb_cf_ports option').each(function(id, obj) {

			if (obj.value == port) {
				$('#cb_cf_ports').prop('selectedIndex', id).change();
				store.selectedPort = port;
				store.serialMonitor = true;
				return false;
			}
		});

		this.dispatch('store.Builder', 'change');
	});

	this.on('store.Builder.setStatus', function *(status) {

		var store = this.getState('Builder');

		store.status = status;

		this.dispatch('store.Builder', 'change');
	});

	this.on('store.Builder.generateCode', function *(workspace) {

		var store = this.getState('Builder');

		// Generate code by using blocky, and reset verify flags
		store.code = window.Blockly.Arduino.workspaceToCode(workspace);
		store.verified = false;

		this.dispatch('store.Builder', 'change');
	});

	this.on('store.Builder.verify', function *(boardId, code) {

		var store = this.getState('Builder');

		// Load source code
		if (code)
			store.files['sketch.ino'] = code;
		else
			store.files['sketch.ino'] = store.code;

		// set specific board with board ID
		for (var index in store.boards_list) {
			var board = store.boards_list[index];

			if (board.id == boardId) {

				// Selecting boards
				$('#cb_cf_boards option').each(function(id, obj) {
					if (obj.value == board.name) {
						$('#cb_cf_boards').prop('selectedIndex', id).change();
						return false;
					}
				});

				break;
			}
		}

		// Start compiled 
		store.compilerflasher.verify();
	});

	this.on('store.Builder.flash', function *(boardId, port, code) {

		var store = this.getState('Builder');

		// Load source code
		if (code)
			store.files['sketch.ino'] = code;
		else
			store.files['sketch.ino'] = store.code;

		// set specific board with board ID
		for (var index in store.boards_list) {
			var board = store.boards_list[index];

			if (board.id == boardId) {

				// Selecting boards
				$('#cb_cf_boards option').each(function(id, obj) {
					if (obj.value == board.name) {
						$('#cb_cf_boards').prop('selectedIndex', id).change();
						return false;
					}
				});

				break;
			}
		}

		// Selecting boards
		$('#cb_cf_ports option').each(function(id, obj) {

			if (obj.value == port) {
				$('#cb_cf_ports').prop('selectedIndex', id).change();
				return false;
			}
		});

		store.status = 'flashing';
		store.serialMinitor = false;

		store.compilerflasher.usbflash();

		this.dispatch('store.Builder', 'change');
	});

	this.on('store.Builder.checkHW', function *(boardId, port) {
		var store = this.getState('Builder');

	});
};
