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

var HTML5Backend = require('react-dnd/modules/backends/HTML5');
var DragDropContext = require('react-dnd').DragDropContext;
var NativeTypes = require('react-dnd/modules/backends/HTML5').NativeTypes;
var update = require('react/lib/update');

var Components = require('./Components.jsx');
var Tips = require('./Tips.jsx');
var Panel = require('./Panel.jsx');

var baseShield = require('../../images/components/base-shield.png');
var baseShieldGrove = require('../../images/components/base-grove-join.png');

class Sensors extends React.Component {
	constructor(props) {
		super(props);

		var workboardStore = Fluky.getState('WorkBoard');
		this.state = {
			'components': workboardStore.modules.sensors,
			'componentSource': workboardStore.modules.sensors,
			'selectName': null
		};
	}

	updateSensors(group, name) {
		var sensorSource = this.state.componentSource;
		var sensors = [];
		if (group === 'all') {
			sensors = sensorSource;
		} else {
			sensorSource.forEach(function (element, index) {
			    var groups = element.group;
			    var sensor = element;
			    groups.forEach(function (element, index) {
			    	if (group === element) {
			    		sensors.push(sensor);
			    	}
			    });
			});
		}

		this.setState({
			'components': sensors,
			'selectName': name
		});
	}

	render() {
		var { components, selectName } = this.state;

		return (
			<div>
				<div className={'col s3 component-list'}>
					<div className={'col s12'}>
						<a className={'dropdown-button btn orange accent-4'} href="#" data-activates="dropdown1">{ selectName || '分类选择' }</a>
						<ul id='dropdown1' className={'dropdown-content'}>
							<li><a href="#!" onClick={ this.updateSensors.bind(this, 'all', '所有元件') }>所有元件</a></li>
							<li><a href="#!" onClick={ this.updateSensors.bind(this, 'input', '传感器') }>传感器</a></li>
							<li><a href="#!" onClick={ this.updateSensors.bind(this, 'output', '执行器') }>执行器</a></li>
							<li><a href="#!">连接通讯</a></li>
							<li><a href="#!" onClick={ this.updateSensors.bind(this, 'analog', '红色 Analog') }>红色 Analog</a></li>
							<li><a href="#!" onClick={ this.updateSensors.bind(this, 'I2C', '绿色 I2C') }>绿色 I2C</a></li>
							<li><a href="#!" onClick={ this.updateSensors.bind(this, 'digital', '蓝色 Digital') }>蓝色 Digital</a></li>
							<li><a href="#!" onClick={ this.updateSensors.bind(this, 'UART', '黄色 UART') }>黄色 UART</a></li>
						</ul>
					</div>
					<div className={'col s12 components-box'}>
						{components.map(({ image, sku, name, color, border, pins, tips, usePorts, io, samples }, index) =>
						<Components image={image}
							sku={sku}
							name={name}
							color={color}
							border={border}
							pins={pins}
							tips={tips}
							usePorts={usePorts}
							io={io}
							samples={samples}
							key={index} />
						)}
					</div>
				</div>
			</div>
		);
	}
}

class WorkBoard extends React.Component {

	constructor() {
		super();

		var builder = Fluky.getState('Builder');
		var store = Fluky.getState('WorkBoard');

		this.state = {
			'connected': {},
			'results': store.testResults || {},
			'compilerflasher': builder.compilerflasher,
			'initialized': builder.initialized,
			'currentPort': builder.selectedPort || null,
			'showToolBar': true,
			'baseShieldImg': baseShield,
			'baseShield': 'baseShield',
		};

		for (var pin in store.connected) {
			var moduleId = store.connected[pin];

			// Finding specific module by sku
			for (var index in store.modules.sensors) {
				var module = store.modules.sensors[index];
				if (module.sku == moduleId) {
					this.state.connected[pin] = module;
					break;
				}
			}
		}
	}

	componentWillMount() {
		Fluky.on('store.WorkBoard', Fluky.bindListener(this.onChange));
		Fluky.on('store.Builder', Fluky.bindListener(this.statusUpdate));
		Fluky.on('store.Tabs', Fluky.bindListener(this.toolBarStatus));
	}

	componentDidMount() {
	}

	componentWillUnmount() {
		Fluky.off('store.WorkBoard', this.onChange);
		Fluky.off('store.Builder', this.statusUpdate);
		Fluky.off('store.Tabs', this.toolBarStatus);
	}

	onChange = () => {
		var store = Fluky.getState('WorkBoard');

		var state = {
			results: store.testResults,
			connected: {}
		};

		for (var pin in store.connected) {
			var moduleId = store.connected[pin];

			// Finding specific module by sku
			for (var index in store.modules.sensors) {
				var module = store.modules.sensors[index];
				if (module.sku == moduleId) {
					state.connected[pin] = module;
					break;
				}
			}
		}

		this.setState(state);
	}

	startSerialMonitor = () => {
		var builder = Fluky.getState('Builder');

		// Receive messages
		var ctx = this;
		var buffer = '';

		// Listen to serial monitor
		builder.compilerflasher.pluginHandler.connected = true;
		builder.compilerflasher.pluginHandler.codebenderPlugin.serialRead(builder.selectedPort, 9600, function(from, chunk) {

			var buf = buffer + chunk;
			var lines = buf.split('\n');

			if (chunk.indexOf('connecting at') == 0) {
				console.log(chunk);
				lines.shift();
			}

			buffer = lines[lines.length - 1];
			lines.length--;

			Fluky.dispatch('action.WorkBoard.updateResults', lines);
		}, function(from, line) {
			console.log('CLOSING', from, line);
		});

	}

	toolBarStatus = () => {
		this.setState({
			'showToolBar': true
		});
	}

	statusUpdate = () => {
		var builder = Fluky.getState('Builder');

		if (builder.serialMonitor) {
			if (builder.status == 'ready' && builder.ports_list.length && !builder.compilerflasher.pluginHandler.connected) {

				console.log('start serial monitor');
				this.startSerialMonitor();
			}
		}

		this.setState({
			'compilerflasher': builder.compilerflasher,
			'currentPort': builder.selectedPort
		});
	}

	showBtns = () => {
		$('.nav-icon').toggleClass('hide');
		$('.tips-icon').toggleClass('hide');
	}

	showTips = () => {
		$('.component-tips').toggleClass('hide');
	}

	showToolBar = () => {
		$('#toolBar').toggleClass('hide');
		var showToolBar = !this.state.showToolBar;

		if (showToolBar) {
			$('.genuino').css("height", "835px");
		} else {
			$('.genuino').css("height", "770px");
		}

		this.setState({
			'showToolBar': showToolBar
		});
	}

	changeBoard = () => {
		if (this.state.baseShield === 'baseShield') {
			this.setState({
				'baseShield': 'baseShieldGrove',
				'baseShieldImg': baseShieldGrove
			});
		} else {
			this.setState({
				'baseShield': 'baseShield',
				'baseShieldImg': baseShield
			});
		}
		Fluky.dispatch('action.WorkBoard.resetAndConnectModules');
	}

	render() {
		var boardStyle;

		if (this.state.showToolBar) {
			boardStyle = {
				marginTop: '65px'
			};
		}else {
			boardStyle = {
				marginTop: '0'
			};
		}
		
		return (
			<div className={'row'} style={boardStyle}>
				<Sensors showToolBar={this.state.showToolBar} />
				<div style={{ display: 'none' }}>
					<div id='cb_cf_serial_monitor'></div>
					<button id='cb_cf_serial_monitor_connect'>Connect</button>
				</div>
				<div className={'col s9'}>
					<div className={ 'tool-icon' }>
						<i className={ 'material-icons' } onClick={ this.showBtns }>dehaze</i>
					</div>
					<div className={ 'nav-icon' }>
						<i className={ 'material-icons' } onClick={ this.showToolBar }>open_in_browser</i>
					</div>
					<div className={ 'tips-icon' }>
						<i className={ 'material-icons' } onClick={ this.showTips }>info</i>
					</div>
					<div className={ 'board-icon' }>
						<i className={ 'material-icons' } onClick={ this.changeBoard }>gradient</i>
					</div>
					<div className={'component-tips'}>
						<Tips />
					</div>
					<div className={'base-shield'}>
						<div className={'row'}>
							<div className={'col s12'}>
								<div className={'col s3 item'}>
									<Panel  module={this.state.connected} pin='A0' board={this.state.baseShield} status={this.state.results['A0'] || {}} accepts='analog' />
								</div>
								<div className={'col s3 item'}>
									<Panel  module={this.state.connected} pin='A1' board={this.state.baseShield} status={this.state.results['A1'] || {}} accepts='analog' />
								</div>
								<div className={'col s3 item'}>
									<Panel  module={this.state.connected} pin='A2' board={this.state.baseShield} status={this.state.results['A2'] || {}} accepts='analog' />
								</div>
								<div className={'col s3 item'}>
									<Panel  module={this.state.connected} pin='A3' board={this.state.baseShield} status={this.state.results['A3'] || {}} accepts='analog' />
								</div>
							</div>
						</div>
						<div className={'row remove-margin-bottom'}>
							<div className={'col s3 panel-left'}>
								<div className={'row'}>
									<div className={'col s12 item panel-bottom'}>
										<Panel  module={this.state.connected} pin='D2' board={this.state.baseShield} status={this.state.results['D2'] || {}} accepts='digital' />
									</div>
									<div className={'col s12 item panel-bottom'}>
										<Panel  module={this.state.connected} pin='D3' board={this.state.baseShield} show='grove' status={this.state.results['D3'] || {}} accepts='digital' />
									</div>
									<div className={'col s12 item'}>
										<Panel  module={this.state.connected} pin='D4' board={this.state.baseShield} status={this.state.results['D4'] || {}} accepts='digital' />
									</div>
								</div>
							</div>
							<div className={'col s6 arduino'}>
								<img src={this.state.baseShieldImg} />
							</div>
							<div className={'col s3'}>
								<div className={'row'}>
									<div className={'col s12 item panel-bottom'}>
										<Panel  module={this.state.connected} pin='I2C1' board={this.state.baseShield} status={this.state.results['I2C1'] || {}} accepts='I2C' />
									</div>
									<div className={'col s12 item panel-bottom'}>
										<Panel  module={this.state.connected} pin='I2C2' board={this.state.baseShield} show='grove' status={this.state.results['I2C2'] || {}} accepts='I2C' />
									</div>
									<div className={'col s12 item'}>
										<Panel  module={this.state.connected} pin='I2C3' board={this.state.baseShield} status={this.state.results['I2C3'] || {}} accepts='I2C' />
									</div>
								</div>
							</div>
						</div>
						<div className={'row'}>
							<div className={'col s12'}>
								<div className={'col s3 item'}>
									<Panel  module={this.state.connected} pin='D5' board={this.state.baseShield} status={this.state.results['D5'] || {}} accepts='digital' />
								</div>
								<div className={'col s3 item'}>
									<Panel  module={this.state.connected} pin='D7' board={this.state.baseShield} status={this.state.results['D7'] || {}} accepts='digital' />
								</div>
								<div className={'col s3 item'}>
									<Panel  module={this.state.connected} pin='UART' board={this.state.baseShield} status={this.state.results['UART'] || {}} accepts='UART' />
								</div>
								<div className={'col s3 item'}>
									<Panel  module={this.state.connected} pin='I2C4' board={this.state.baseShield} status={this.state.results['I2C4'] || {}} accepts='I2C' />
								</div>
							</div>
						</div>
						<div className={'row'}>
							<div className={'col s12'}>
								<div className={'col s3 item'}>
									<Panel  module={this.state.connected} pin='D6' board={this.state.baseShield} status={this.state.results['D6'] || {}} accepts='digital' />
								</div>
								<div className={'col s3 item'}>
									<Panel  module={this.state.connected} pin='D8' board={this.state.baseShield} status={this.state.results['D8'] || {}} accepts='digital' />
								</div>
							</div>
						</div>
					</div>
				</div>
			</div>
		);
	};
};

module.exports = DragDropContext(HTML5Backend)(WorkBoard);
