var React = require('react');

var Motherboard = function(options) {
	this.layout = null;
	this.chipInstances = []; // [{name: '', instance: null}]
	
	this.ACTIONS = options.ACTIONS || {};
	this.SLOTS = options.SLOTS || {};
	
	this.callbacks = {};
	
	console.log('new Motherboard', this.ACTIONS, this.SLOTS);
};

Motherboard.prototype.register = function(actionType, cb) {
	if(this.callbacks[actionType])
		this.callbacks[actionType].push(cb);
	else
		this.callbacks[actionType] = [cb];
};

Motherboard.prototype.emit = function(action) {
	this.callbacks[action.type].forEach(function(cb) {
		cb(action.payload);
	});
};

Motherboard.prototype.addLayout = function(layout /* ReactClass */) {
	console.log('MB.addLayout', layout);
	// inject motherboard reference to layout
	layout.prototype.MB = this;
	
	var didMountFunc = layout.prototype.componentDidMount,
		that = this;
		
	layout.prototype.componentDidMount = function() {
		var layout_this = this;
		didMountFunc();
		
		that.chipInstances.forEach(function(instance) {
			var name = instance.name;
			React.render(instance.instance, layout_this.refs[name].getDOMNode());
		});
	};
	
	this.layout = layout;
};

Motherboard.prototype.addChip = function(name /* slot name */, chip /* ReactElement */) {
	console.log('MB.addChip', name, chip);
	if(this.SLOTS[name]) {
		// inject motherboard reference to chip instance
		var reactType = chip.type;
		reactType.prototype.MB = this;
		
		this.chipInstances.push({name: name, instance: chip});
	} else {
		console.err('MB', 'can not find the slot: ' + name);
	}
};

Motherboard.prototype.run = function(mountNode) {
	console.log('MB.run');
	React.render(React.createElement(this.layout), mountNode);
};


// test code
Motherboard.test = function() {
	console.log('running test');
	
	var mb = new Motherboard({
		ACTIONS: {CLICK: 'CLICK', STOREUPDATE: 'STOREUPDATE'},
		SLOTS: {SIDEBAR: 'SIDEBAR', CONTENT: 'CONTENT', STORE: 'STORE'},
	});
	
	var Sidebar = React.createClass({
		handleClick: function(e) {
			console.log('Sidebar handleClick', this.MB.ACTIONS.CLICK);
			this.MB.emit({type: this.MB.ACTIONS.CLICK, payload: 'hello'});
		},
		render: function() {
			return (
				<div>
					<button onClick={this.handleClick}>{this.props.value}</button>
				</div>
			);
		}
	});
	
	var Content = React.createClass({
		getInitialState: function() {
			return {
				content: 'placeholder'
			};
		},
		componentDidMount: function() {
			this.MB.register(this.MB.ACTIONS.CLICK, function(payload) {
				console.log('i got it!!! ' + payload);
			});
			var that = this;
			this.MB.register(this.MB.ACTIONS.STOREUPDATE, function(payload) {
				that.setState({content: payload});
			});
		},
		render: function() {
			return (
				<div>
					<p>{this.state.content}</p>
				</div>
			);
		}
	});
	
	var Store = React.createClass({
		getInitialState: function() {
			return {
				store: ' '
			};
		},
		componentDidMount: function() {
			var that = this;
			this.MB.register(this.MB.ACTIONS.CLICK, function(payload) {
				that.setState({store: that.state.store + ',' + payload});
				that.MB.emit({type: that.MB.ACTIONS.STOREUPDATE, payload: that.state.store});
			});
		},
		render: function() {
			return (
				<div></div>
			);
		}
	});
	
	mb.addLayout(React.createClass({
		componentDidMount: function() {
			console.log('layout existing componentDidMount');
		},
		render: function() {
			var style = {
					border: '1px solid black',
					padding: '5px'
				},
				layoutStyle = {
					display: 'flex',
					flexDirection: 'row'
				};
			return (
				<div>
					<h4>motherboard layout</h4>
					<div style={layoutStyle}>
					<div style={style} ref={mb.SLOTS.SIDEBAR}></div>
					<div style={style} ref={mb.SLOTS.CONTENT}></div>
					<div ref={mb.SLOTS.STORE}></div>
					</div>
				</div>
			);
		}
	}));
	
	mb.addChip(mb.SLOTS.SIDEBAR, <Sidebar value='new button 2' />);
	mb.addChip(mb.SLOTS.CONTENT, <Content />);
	mb.addChip(mb.SLOTS.STORE, <Store />);
	
	mb.run(mountNode);
}

module.exports = Motherboard;