import _ from 'underscore';
import classnames from 'classnames';
import evalDependsOn from '../utils/evalDependsOn.js';
import React from 'react';
import ReactDOM from 'react-dom';
import { Button, FormField, FormInput, FormNote } from 'elemental';

function validateSpec(spec) {
	if (!spec) spec = {};
	if (!_.isObject(spec.supports)) {
		spec.supports = {};
	}
	if (!spec.focusTargetRef) {
		spec.focusTargetRef = 'focusTarget';
	}
	return spec;
}

var Base = module.exports.Base = {
	getInitialState () {
		return {};
	},
	getDefaultProps () {
		return {
			inputProps: {},
			labelProps: {},
			valueProps: {},
			size: 'full'
		};
	},
	valueChanged (event) {
		this.props.onChange({
			path: this.props.path,
			value: event.target.value
		});
	},
	shouldCollapse () {
		return this.props.collapse && !this.props.value;
	},
	shouldRenderField () {
		if (!this.props.noedit) return true;
		if (this.props.mode === 'create' && this.props.initial) return true;
		return false;
	},
	focus () {
		if (!this.refs[this.spec.focusTargetRef]) return;
		ReactDOM.findDOMNode(this.refs[this.spec.focusTargetRef]).focus();
	},
	renderNote () {
		if (!this.props.note) return null;
		return <FormNote note={this.props.note} />;
	},
	renderField () {
		var props = Object.assign(this.props.inputProps, {
			autoComplete: 'off',
			name: this.props.path,
			onChange: this.valueChanged,
			ref: 'focusTarget',
			value: this.props.value
		});
		return <FormInput {...props} />;
	},
	renderValue () {
		return <FormInput noedit>{this.props.value}</FormInput>;
	},
	renderUI () {
		var wrapperClassName = classnames(
			('field-type-' + this.props.type),
			this.props.className
		);
		return (
			<FormField label={this.props.label} className={wrapperClassName} htmlFor={this.props.path}>
				<div className={'FormField__inner field-size-' + this.props.size}>
					{this.shouldRenderField() ? this.renderField() : this.renderValue()}
				</div>
				{this.renderNote()}
			</FormField>
		);
	}
};

var Mixins = module.exports.Mixins = {
	Collapse: {
		componentWillMount () {
			this.setState({
				isCollapsed: this.shouldCollapse()
			});
		},
		componentDidUpdate (prevProps, prevState) {
			if (prevState.isCollapsed && !this.state.isCollapsed) {
				this.focus();
			}
		},
		uncollapse () {
			this.setState({
				isCollapsed: false
			});
		},
		renderCollapse () {
			if (!this.shouldRenderField()) return null;
			return (
				<FormField>
					<Button type="link" className="collapsed-field-label" onClick={this.uncollapse}>+ Add {this.props.label.toLowerCase()}</Button>
				</FormField>
			);
		}
	}
};

module.exports.create = function(spec) {

	spec = validateSpec(spec);

	var excludeBaseMethods = [];
	var field = {
		spec: spec,
		displayName: spec.displayName,
		mixins: [Mixins.Collapse],
		render () {
			if (!evalDependsOn(this.props.dependsOn, this.props.values)) {
				return null;
			}
			if (this.state.isCollapsed) {
				return this.renderCollapse();
			}
			return this.renderUI();
		}
	};

	if (spec.mixins) {
		_.each(spec.mixins, function(mixin) {
			_.each(mixin, function(method, name) {
				if (Base[name]) excludeBaseMethods.push(name);
			});
		});
	}

	Object.assign(field, _.omit(Base, excludeBaseMethods));
	Object.assign(field, _.omit(spec, 'mixins'));

	if (_.isArray(spec.mixins)) {
		field.mixins = field.mixins.concat(spec.mixins);
	}

	return React.createClass(field);

};

@@ -1,32 +1,4 @@
-import _ from 'underscore';%0A
 impo
@@ -213,16 +213,146 @@
 mental';
+%0Aimport blacklist from 'blacklist';%0A%0Afunction isObject(arg) %7B%0A%09return Object.prototype.toString.call(arg) === '%5Bobject Object%5D';%0A%7D
 %0A%0Afuncti
@@ -404,18 +404,16 @@
 ;%0A%09if (!
-_.
 isObject
@@ -2771,38 +2771,8 @@
 );%0A%0A
-%09var excludeBaseMethods = %5B%5D;%0A
 %09var
@@ -3068,16 +3068,46 @@
 %09%7D%0A%09%7D;%0A%0A
+%09var excludeBaseMethods = %7B%7D;%0A
 %09if (spe
@@ -3120,23 +3120,16 @@
 ns) %7B%0A%09%09
-_.each(
 spec.mix
@@ -3131,18 +3131,25 @@
 c.mixins
-, 
+.forEach(
 function
@@ -3165,22 +3165,35 @@
 %0A%09%09%09
-_.each(mixin, 
+Object.keys(mixin).forEach(
 func
@@ -3201,16 +3201,8 @@
 ion(
-method, 
 name
@@ -3225,16 +3225,23 @@
 %5Bname%5D) 
+%7B%0A%09%09%09%09%09
 excludeB
@@ -3254,20 +3254,28 @@
 hods
-.push(name);
+%5Bname%5D = true;%0A%09%09%09%09%7D
 %0A%09%09%09
@@ -3310,21 +3310,24 @@
 (field, 
-_.omi
+blacklis
 t(Base, 
@@ -3374,13 +3374,16 @@
 ld, 
-_.omi
+blacklis
 t(sp
@@ -3404,17 +3404,21 @@
 ;%0A%0A%09if (
-_
+Array
 .isArray

Remove `underscore` dependency in `types/Fields`