var __extends = (this && this.__extends) || (function () {
    var extendStatics = function (d, b) {
        extendStatics = Object.setPrototypeOf ||
            ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
            function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
        return extendStatics(d, b);
    };
    return function (d, b) {
        extendStatics(d, b);
        function __() { this.constructor = d; }
        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
    };
})();
var __assign = (this && this.__assign) || function () {
    __assign = Object.assign || function(t) {
        for (var s, i = 1, n = arguments.length; i < n; i++) {
            s = arguments[i];
            for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
                t[p] = s[p];
        }
        return t;
    };
    return __assign.apply(this, arguments);
};
import * as _ from "lodash";
import * as classnames from "classnames";
import * as PropTypes from "prop-types";
import * as React from "react";
import Checkbox from "../Checkbox";
import FormError from "../FormError";
import "./CheckboxGroup.less";
var OPTION_PROP_TYPE = PropTypes.shape({
    id: PropTypes.string.isRequired,
    checked: PropTypes.bool,
    disabled: PropTypes.bool,
    label: PropTypes.node.isRequired,
    value: PropTypes.any,
});
var propTypes = {
    className: PropTypes.string,
    disabled: PropTypes.bool,
    error: PropTypes.node,
    label: PropTypes.node.isRequired,
    onChange: PropTypes.func.isRequired,
    options: PropTypes.arrayOf(OPTION_PROP_TYPE).isRequired,
    title: PropTypes.node,
};
var cssClass = {
    CHECKBOX: "CheckboxGroup--checkbox",
    CHECKBOX_GLOBAL: "CheckboxGroup--checkbox--global",
    CONTAINER: "CheckboxGroup",
    LABEL: "CheckboxGroup--label",
    SUB_OPTIONS: "CheckboxGroup--subOptions",
};
var LABEL_ID_PREFIX = "CheckboxGroup--label";
var nextLabelIDSuffix = 0;
var getNextLabelID = function () { return LABEL_ID_PREFIX + "--" + nextLabelIDSuffix++; };
/**
 * Renders a group of related checkboxes that can all be checked/unchecked together by clicking a
 * parent checkbox, or separately by clicking each individual checkbox.
 *
 * TODO: Add support for resetting the options to their initial state when going from all unchecked
 * to partially checked as per
 * https://www.w3.org/TR/wai-aria-practices-1.1/examples/checkbox/checkbox-2/checkbox-2.html
 *
 * W3C spec: https://www.w3.org/TR/wai-aria-practices-1.1/#checkbox
 */
var CheckboxGroup = /** @class */ (function (_super) {
    __extends(CheckboxGroup, _super);
    function CheckboxGroup() {
        var _this = _super !== null && _super.apply(this, arguments) || this;
        _this._labelID = getNextLabelID();
        _this._optionRefsByID = {};
        _this._handleGlobalChange = function (_a) {
            var checked = _a.checked;
            var _b = _this.props, onChange = _b.onChange, options = _b.options;
            onChange(_.map(options, function (o) { return (__assign(__assign({}, o), { checked: checked })); }));
        };
        _this._handleSingleChange = function (_a) {
            var id = _a.id, checked = _a.checked;
            var _b = _this.props, onChange = _b.onChange, options = _b.options;
            onChange(_.map(options, function (o) { return (__assign(__assign({}, o), { checked: o.id === id ? checked : o.checked })); }));
        };
        return _this;
    }
    CheckboxGroup.prototype.render = function () {
        var _this = this;
        var _a = this.props, className = _a.className, disabled = _a.disabled, error = _a.error, label = _a.label, options = _a.options, title = _a.title;
        var allChecked = _.every(options, function (o) { return o.checked; });
        var someChecked = _.some(options, function (o) { return o.checked; });
        return (React.createElement("div", { "aria-labelledby": this._labelID, className: classnames(cssClass.CONTAINER, className), role: "group" },
            React.createElement("div", { className: cssClass.LABEL, id: this._labelID }, title),
            error && React.createElement(FormError, null, error),
            React.createElement(Checkbox, { checked: someChecked, className: cssClass.CHECKBOX_GLOBAL, disabled: !!disabled, id: "global", onChange: this._handleGlobalChange, partial: someChecked && !allChecked }, label),
            React.createElement("div", { className: cssClass.SUB_OPTIONS }, _.map(options, function (o) { return (React.createElement(Checkbox, { checked: o.checked, className: cssClass.CHECKBOX, disabled: !!disabled || !!o.disabled, id: o.id, key: o.id, onChange: _this._handleSingleChange, value: o.value }, o.label)); }))));
    };
    CheckboxGroup.propTypes = propTypes;
    return CheckboxGroup;
}(React.PureComponent));
export default CheckboxGroup;
