// dependencies
//
import React from 'react';
import update from 'react-addons-update';
import uniqueId from 'lodash/uniqueId';
import isArray from 'lodash/isArray';
import classnames from 'classnames';

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

        let value = [];

        if (this.props.value) {
            value = isArray(this.props.value) ? this.props.value : [this.props.value];
        }

        this.id = this.props.id || uniqueId('form-checkboxgroup-');

        // intialize the validation message for the component
        //
        this.validationMessage = this.props.validationMessage
            || `At least one item in ${this.props.description} must be selected`;


        this.state = {
            value,
            hasBeenClicked: false,
        };

        this.onClick = this.onClick.bind(this);
    }

    componentWillMount() {
        // determine if it's valid
        //
        const isValid = !this.props.required || this.state.value.length;

        // call the `onChildValidationEvent` handler once with
        // `hasValidated`=false, just to ensure that the parent knows about this
        // child
        //
        if (this.context.onChildValidationEvent) {
            this.context.onChildValidationEvent(
                this.id,
                false,
                isValid ? null : this.validationMessage
            );
        }
    }

    onClick(value) {
        const idx = this.state.value.findIndex((val) => val === value);

        let delta = null;
        if (idx === -1) {
            delta = { hasBeenClicked: { $set: true }, value: { $push: [value] } };
        } else {
            delta = { hasBeenClicked: { $set: true }, value: { $splice: [[idx, 1]] } };
        }

        this.setState((state) => update(state, delta), () => {
            if (this.props.onChange) {
                this.props.onChange(this.state.value);
            }

            const isValid = !this.props.required || this.state.value.length;

            if (this.context.onChildValidationEvent) {
                this.context.onChildValidationEvent(
                    this.id,
                    true,
                    isValid ? null : this.validationMessage
                );
            }
        });
    }

    render() {

        const classes = classnames('form-group', {
            'has-error': this.props.required
                && this.state.hasBeenClicked
                && !this.state.value.length,
        });

        const helpBlock =
            this.props.required && this.state.hasBeenClicked && !this.state.value.length
            ? <span className="help-block">{this.validationMessage}</span>
            : '';

        return (
            <div className={classes}>
                {this.props.label
                    ? <label className="checkboxgroup">{this.props.label}</label>
                    : null
                }
                {this.props.options.map((opt) =>
                    <div
                        key={uniqueId('form-checkboxgroup-option-')}
                        className="checkbox pull-left"
                    >
                        <label>
                            <input
                                type="checkbox"
                                value={opt.value}
                                checked={
                                    this.state.value.findIndex((val) => val === opt.value) !== -1
                                }
                                onChange={() => this.onClick(opt.value)}
                                onClick={() => this.onClick(opt.value)}
                            />
                            <span>{opt.name}</span>
                        </label>
                    </div>
                )}
                {helpBlock}
            </div>
        );
    }
}

CheckboxGroup.propTypes = {
    required:          React.PropTypes.bool,
    id:                React.PropTypes.string,
    label:             React.PropTypes.string,
    description:       React.PropTypes.string,
    validationMessage: React.PropTypes.string,
    onChange:          React.PropTypes.func,
    value:             React.PropTypes.oneOfType([
        React.PropTypes.string,
        React.PropTypes.number,
    ]),
    options:           React.PropTypes.oneOfType([
        React.PropTypes.arrayOf(
            React.PropTypes.oneOfType([
                React.PropTypes.string,
                React.PropTypes.number,
            ])
        ),
        React.PropTypes.string,
        React.PropTypes.number,
    ]),

};

// set the context types for values received from higher up the food chain
//
CheckboxGroup.contextTypes = {
    onChildValidationEvent: React.PropTypes.func,
};

export default CheckboxGroup;

@@ -197,16 +197,55 @@
 ames';%0A%0A
+/**%0A * The CheckboxGroup component%0A */%0A
 class Ch
@@ -290,76 +290,375 @@
     
-constructor(props) %7B%0A        super(props);%0A%0A        let value = %5B%5D;%0A
+/**%0A     * Construct the component instance%0A     * @param  %7BObject%7D props The component properties%0A     */%0A    constructor(props) %7B%0A        super(props);%0A%0A        // declare a variable for the component value%0A        //%0A        let value = %5B%5D;%0A%0A        // do we have a value prop? if so, make sure it's either an array, or%0A        // convert it to an array%0A        //
 %0A   
@@ -776,32 +776,117 @@
 ue%5D;%0A        %7D%0A%0A
+        // calculate a unique ID for the component if one is not provided%0A        //%0A
         this.id 
@@ -1157,16 +1157,69 @@
 ted%60;%0A%0A%0A
+        // initialize the component state%0A        //%0A
         
@@ -1299,16 +1299,73 @@
     %7D;%0A%0A
+        // bind %60this%60 to the onClick handler%0A        //%0A
         

comment cleanup