import React from 'react';
import Fluky from 'fluky';

// Blockly dependencies
require('!file?name=blockly.js!../../blockly/blockly_compressed.js');
require('!file?name=blocks.js!../../blockly/blocks_compressed.js');
require('!file?name=arduino.js!../../blockly/arduino_compressed.js');
require('!file?name=blockly-en.js!../../blockly/msg/js/en.js');
require('!file?name=blockly-cn.js!../../blockly/msg/js/zh-hans.js');
require('!file?name=blockly/sprites.png!../../media/sprites.png');
require('!file?name=blockly/click.mp3!../../media/click.mp3');
require('!file?name=blockly/delete.mp3!../../media/delete.mp3');

class Blockly extends React.Component {

	constructor(props) {
		super(props);

		var blocklyStore = Fluky.getState('Blockly');

		this.state = {
			workspace: blocklyStore.workspace,
			toolbox: blocklyStore.toolbox,
			modules: blocklyStore.registered
		};
	}

	componentWillMount() {
		Fluky.on('store.Blockly', Fluky.bindListener(this.onChange));
	}

	componentWillUnmount() {
		Fluky.off('store.Blockly', this.onChange);
	}

	componentDidMount() {
		this.refs.variables.getDOMNode().setAttribute('custom', 'VARIABLE');
		this.refs.functions.getDOMNode().setAttribute('custom', 'PROCEDURE');

		var content_area = React.findDOMNode(this.refs.content_area);
		var toolbox = React.findDOMNode(this.refs.toolbox);

		var workspace = window.Blockly.inject(content_area, {
			media: '/assets/blockly/',
			toolbox: toolbox,
			grid: {
				spacing: 20,
				length: 5,
				color: '#ddd',
				snap: true
			}
		});
/*
		var onresize = function() {
			var container = this.refs.container.getDOMNode();
			var area = this.refs.content_area.getDOMNode();

			var element = container;
			var x = 0;
			var y = 0;
			do {
				x += element.offsetLeft;
				y += element.offsetTop;
				element = element.offsetParent;
			} while (element);

			area.style.left = x + 'px';
			area.style.top = y + 'px';
			area.style.width = container.offsetWidth + 'px';
			area.style.height = container.offsetHeight + 'px';
		}.bind(this);

		window.addEventListener('resize', onresize, false);

		onresize();
*/
		Fluky.dispatch('action.Blockly.initialize', workspace, toolbox);
	}

	componentDidUpdate() {

		//var $toolbox = $(this.state.toolbox).empty();
		var $toolbox = $(this.state.toolbox);
		var $components = $(this.refs.components.getDOMNode()).empty();
/*
		// control
		var $control = $('<category />').attr('name', 'Control')
			.append($('<block />').attr('type', 'controls_if'))
			.append($('<block />').attr('type', 'controls_whileUntil'))
		var $logic = $('<category />').attr('name', 'Logic')
			.append($('<block />').attr('type', 'logic_compare'))
			.append($('<block />').attr('type', 'logic_operation'))
			.append($('<block />').attr('type', 'logic_boolean'))
*/
		// for
/*
		var $math_number = $('<block />').attr('type', 'math_number');
		var $field_num = $('<field />').attr('name', 'NUM').text(1);
		var $fromDef = $('<value />').attr('name', 'FROM').append($math_number.clone().append($field_num.clone()));
		var $toDef = $('<value />').attr('name', 'TO').append($math_number.clone().append($field_num.clone().text(10)));
		var $byDef = $('<value />').attr('name', 'BY').append($math_number.clone().append($field_num.clone()));
		var $controls_for = $('<block />').attr('type', 'controls_for')
			.append($fromDef)
			.append($toDef)
			.append($byDef);
*/
		/*
		$toolbox
			.append($control)
			.append($logic)
*/
		/*
			.append($('<block />').attr('type', 'controls_whileUntil'))
			.append($controls_for);
*/
		// Available modules for hardware
		var workboardStore = Fluky.getState('WorkBoard');

		// Generate block
		for (var index in this.state.modules) {
			var m = this.state.modules[index];

			var $block = $('<block />').attr('type', m.type);

			// Value blocks
			for (var fieldName in m.values) {
				var v = m.values[fieldName];

				var $value = $('<value />').attr('name', fieldName);
				var $valueBlock = $('<block />').attr('type', v.type);
				var $field = $('<field />').attr('name', 'NUM').text(v.defValue);

				$valueBlock.append($field);
				$value.append($valueBlock);
				$block.append($value);
			}
			//$toolbox.append($block);
			$components.append($block);
		}
		if (Object.keys(this.state.modules).length > 0)
			$components.attr('name', '已连接模块(' + Object.keys(this.state.modules).length + ')');
		else
			$components.attr('name', '无已连接模块');

		// Update toolbox now
		this.state.workspace.updateToolbox($toolbox[0].outerHTML);

		var onresize = function() {
			var container = this.refs.container.getDOMNode();
			var area = this.refs.content_area.getDOMNode();

			var element = container;
			var x = 0;
			var y = 0;
			do {
				x += element.offsetLeft;
				y += element.offsetTop;
				element = element.offsetParent;
			} while (element);

			area.style.left = x + 'px';
			area.style.top = y + 'px';
			area.style.width = container.offsetWidth + 'px';
			area.style.height = container.offsetHeight + 'px';
		}.bind(this);
		onresize();
	}

	generateCode = () => {
		/*
		return;
		var code = window.Blockly.Arduino.workspaceToCode(this.state.workspace);
		//this.state.workspace.updateToolbox(temp);
		//delete Blockly.Blocks['grove_led'];
		var xml = window.Blockly.Xml.workspaceToDom(this.state.workspace);
		var xml_text = window.Blockly.Xml.domToText(xml);

		alert(xml_text);
		*/
	}

	onChange = () => {
		var blocklyStore = Fluky.getState('Blockly');
		this.setState({
			workspace: blocklyStore.workspace,
			toolbox: blocklyStore.toolbox,
			modules: blocklyStore.registered
		});
		//console.log('Update');
	}

	render() {
		var style = {
			height: '640px',
			marginTop: '10px'
		};
		var containerStyle = {
			height: '640px'
		};
		var areaStyle = {
			position: 'absolute'
		};
		var toolboxStyle = {
			display: 'none',
			position: 'relative'
		};

		return (
			<div style={style} onClick={this.generateCode}>
				<div ref='container' style={containerStyle}></div>
				<div ref='content_area' id='content_area' style={areaStyle}></div>
				<xml ref='toolbox' id='toolbox' style={toolboxStyle}>
					<category ref='components' name="无已连接模块">
					</category>
					<sep />
					<sep />
					<category name="常用">
						<block type="controls_if" dangerouslySetInnerHTML={{ __html: '<mutation else="1"></mutation>'}}>
						</block>
						<block type="math_number"></block>
						<block type="logic_compare"></block>
						<block type="base_delay">
							<value name="DELAY_TIME">
								<block type="math_number">
									<field name="NUM">10</field>
								</block>
							</value>
						</block>
						<block type="variables_set"></block>
						<block type="variables_get"></block>
						<block type="high_low"></block>
					</category>
					<sep />

					<category name="逻辑">
						<block type="light_switch"></block>
						<block type="high_low"></block>
						<category name="如果">
							<block type="controls_if"></block>
							<block type="controls_if" dangerouslySetInnerHTML={{ __html: '<mutation else="1"></mutation>'}}>
							</block>
							<block type="controls_if" dangerouslySetInnerHTML={{ __html: '<mutation elseif="1" else="1"></mutation>' }}>
							</block>
						</category>
						<category name="布尔">
							<block type="logic_compare"></block>
							<block type="logic_operation"></block>
							<block type="logic_negate"></block>
							<block type="logic_boolean"></block>
							<block type="logic_null"></block>
							<block type="logic_ternary"></block>
						</category>
					</category>
					<category name="重复执行">
						<block type="base_delay">
							<value name="DELAY_TIME">
								<block type="math_number">
									<field name="NUM">10</field>
								</block>
							</value>
						</block>
						<block type="controls_repeat_ext">
							<value name="TIMES">
								<block type="math_number">
									<field name="NUM">10</field>
								</block>
							</value>
						</block>
						<block type="controls_whileUntil"></block>
						<block type="controls_for">
							<field name="VAR">i</field>
							<value name="FROM">
								<block type="math_number">
									<field name="NUM">1</field>
								</block>
							</value>
							<value name="TO">
								<block type="math_number">
									<field name="NUM">10</field>
								</block>
							</value>
							<value name="BY">
								<block type="math_number">
									<field name="NUM">1</field>
								</block>
							</value>
						</block>
						<block type="controls_flow_statements"></block>
					</category>
					<category name="数学计算">
						<block type="math_number"></block>
						<block type="math_arithmetic"></block>
						<block type="math_single"></block>
						<block type="math_trig"></block>
						<block type="math_constant"></block>
						<block type="math_number_property"></block>
						<block type="math_change">
							<value name="DELTA">
								<block type="math_number">
									<field name="NUM">1</field>
								</block>
							</value>
						</block>
						<block type="math_round"></block>
						<block type="math_modulo"></block>
						<block type="math_constrain">
							<value name="LOW">
								<block type="math_number">
									<field name="NUM">1</field>
								</block>
							</value>
							<value name="HIGH">
								<block type="math_number">
									<field name="NUM">100</field>
								</block>
							</value>
						</block>
						<block type="math_random_int">
							<value name="FROM">
								<block type="math_number">
									<field name="NUM">1</field>
								</block>
							</value>
							<value name="TO">
								<block type="math_number">
									<field name="NUM">100</field>
								</block>
							</value>
						</block>
						<block type="math_random_float"></block>
					</category>
					<category ref='variables' name="变量"></category>
					<category ref='functions' name="函数"></category>
					<category name="初始化工作">
						<block type="entry"></block>
					</category>
				</xml>
			</div>
		);
	}
}
/*
					<category ref='component_controls' name="模塊控制">
						<block type='component_getter'></block>
					</category>
*/
module.exports = Blockly;
