"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
    var ownKeys = function(o) {
        ownKeys = Object.getOwnPropertyNames || function (o) {
            var ar = [];
            for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
            return ar;
        };
        return ownKeys(o);
    };
    return function (mod) {
        if (mod && mod.__esModule) return mod;
        var result = {};
        if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
        __setModuleDefault(result, mod);
        return result;
    };
})();
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.InformalTaxonGroupChooser = void 0;
exports.getInformalGroups = getInformalGroups;
const React = __importStar(require("react"));
const PropTypes = __importStar(require("prop-types"));
const components_1 = require("../components");
const Context_1 = __importDefault(require("../../Context"));
const ReactContext_1 = __importDefault(require("../../ReactContext"));
const react_spinner_1 = __importDefault(require("react-spinner"));
const utils_1 = require("../../utils");
class InformalTaxonGroupChooserWidget extends React.Component {
    constructor(props) {
        super(props);
        this.getDefaultOptions = (props) => {
            const { button = true, rootOnly = false, grid = { lg: 1, md: 2, sm: 3, xs: 12 } } = (0, utils_1.getUiOptions)(props);
            return { button, rootOnly, grid };
        };
        this.onSelected = (id) => {
            this.props.onChange(id);
            const { button } = this.getDefaultOptions(this.props);
            if (button)
                this.hide();
            if (this.state.informalTaxonGroupsById && id)
                this.setState({ informalTaxonGroup: this.state.informalTaxonGroupsById[id] });
        };
        this.show = () => {
            this.setState({ show: true });
        };
        this.hide = () => {
            this.setState({ show: false });
        };
        this.onClear = (e) => {
            e.stopPropagation();
            this.onSelected(undefined);
        };
        this.state = {};
    }
    componentDidMount() {
        this.mounted = true;
        getInformalGroups(this.props.formContext.apiClient).then(state => {
            if (!this.mounted)
                return;
            this.setState(state);
        });
        this.UNSAFE_componentWillReceiveProps(this.props);
    }
    UNSAFE_componentWillReceiveProps(props) {
        if (props.value !== this.state.informalTaxonGroup) {
            if (!props.value)
                this.setState({ name: undefined });
            getInformalGroups(props.formContext.apiClient).then(({ informalTaxonGroupsById }) => {
                if (!this.mounted)
                    return;
                this.setState({ informalTaxonGroup: informalTaxonGroupsById[this.props.value] });
            });
        }
    }
    componentWillUnmount() {
        this.mounted = false;
    }
    render() {
        let imageID = this.props.value;
        const { disabled, readonly } = this.props;
        const { button, rootOnly, grid } = this.getDefaultOptions(this.props);
        const { informalTaxonGroupsById = {} } = this.state;
        if (informalTaxonGroupsById[this.props.value] && informalTaxonGroupsById[this.props.value].parent) {
            imageID = informalTaxonGroupsById[this.props.value].parent.id;
        }
        const InformalTaxonGroupChooserComponent = (React.createElement(InformalTaxonGroupChooser, { modal: button, onHide: this.hide, activeId: this.props.value, onSelected: this.onSelected, formContext: this.props.formContext, lang: this.props.formContext.lang, rootOnly: rootOnly, grid: grid }));
        const { Button } = this.context.theme;
        if (button) {
            const title = !this.props.value
                ? React.createElement("div", { className: "informal-group-chooser-button-content" },
                    React.createElement("span", null, this.props.formContext.translations.PickInformalTaxonGroup))
                : (React.createElement("div", { className: "informal-group-chooser-button-content" },
                    React.createElement("div", { className: `informal-group-image ${imageID}` }),
                    this.state.informalTaxonGroup ? React.createElement("span", null, this.state.informalTaxonGroup.name) : React.createElement(react_spinner_1.default, null),
                    React.createElement("div", { className: "close", onClick: this.onClear }, "\u00D7")));
            return (React.createElement(components_1.TooltipComponent, { tooltip: this.state.informalTaxonGroup && this.state.informalTaxonGroup.name },
                React.createElement("div", { className: "informal-taxon-groups-list" },
                    React.createElement(Button, { onClick: this.show, disabled: disabled || readonly }, title),
                    this.state.show && InformalTaxonGroupChooserComponent)));
        }
        else {
            return InformalTaxonGroupChooserComponent;
        }
    }
}
InformalTaxonGroupChooserWidget.contextType = ReactContext_1.default;
InformalTaxonGroupChooserWidget.propTypes = {
    schema: PropTypes.shape({
        type: PropTypes.oneOf(["string"])
    }),
    value: PropTypes.string
};
exports.default = InformalTaxonGroupChooserWidget;
function walk(allGroups, _group, parent) {
    _group.forEach(group => {
        allGroups[group.id] = group;
        if (parent)
            group.parent = parent;
        if (group.hasSubGroup) {
            allGroups = walk(allGroups, group.hasSubGroup, parent || group);
        }
    });
    return allGroups;
}
const mapGroupsById = _groups => _groups.reduce((groups, group) => {
    groups[group.id] = group;
    return groups;
}, {});
let informalTaxonGroups, informalTaxonGroupsById;
function getInformalGroups(apiClient) {
    if (informalTaxonGroups) {
        return Promise.resolve({ informalTaxonGroups, informalTaxonGroupsById });
    }
    return apiClient.get("/informal-taxon-groups/tree").then(response => {
        // Contains the current taxon group.
        const informalTaxonGroups = mapGroupsById(response.results);
        // Contains all groups in flat object.
        const informalTaxonGroupsById = walk({}, response.results);
        (0, Context_1.default)().informalTaxonGroupsById = informalTaxonGroupsById;
        return Promise.resolve({ informalTaxonGroups, informalTaxonGroupsById });
    });
}
class InformalTaxonGroupChooser extends React.Component {
    constructor(props) {
        super(props);
        this.onSelected = (id) => () => {
            this.props.onSelected(id);
        };
        this.onSubgroupSelected = (id) => () => {
            let path;
            const existingIdx = this.state.path.indexOf(id);
            path = (existingIdx >= 0)
                ? this.state.path.slice(0, existingIdx + 1)
                : [...this.state.path, id];
            this.setState({
                informalTaxonGroups: id
                    ? mapGroupsById(this.state.informalTaxonGroupsById[id].hasSubGroup)
                    : this.state.root,
                path
            });
        };
        this.Container = ({ children }) => {
            const { modal, onHide } = this.props;
            const { translations } = this.props.formContext;
            const { Modal } = this.context.theme;
            return modal ? (React.createElement(Modal, { show: true, onHide: onHide, dialogClassName: "laji-form informal-taxon-group-chooser" },
                React.createElement(Modal.Header, { closeButton: true },
                    React.createElement(Modal.Title, null, translations.PickInformalTaxonGroup)),
                React.createElement(Modal.Body, null, children))) : (React.createElement("div", { className: "informal-taxon-group-chooser" }, children));
        };
        this.getButtonGroup = (id) => {
            const { translations } = this.props.formContext;
            const { informalTaxonGroupsById } = this.state;
            const { Button, ButtonGroup } = this.context.theme;
            return (React.createElement(ButtonGroup, null,
                informalTaxonGroupsById[id].hasSubGroup && React.createElement(Button, { key: "subgroups", onClick: this.onSubgroupSelected(id) }, translations.ShowSubgroups),
                React.createElement(Button, { key: "select", onClick: this.onSelected(id) }, translations.Select)));
        };
        this.getLabel = (id) => {
            const { path, informalTaxonGroupsById } = this.state;
            const name = informalTaxonGroupsById[id].name;
            return path.length <= 1 ? React.createElement("h5", null, name) : React.createElement("span", null, name);
        };
        this.GroupsContainer = ({ children }) => {
            const { rootOnly } = this.props;
            const { Row } = this.context.theme;
            const { ListGroup } = this.context.theme;
            return rootOnly ? React.createElement(Row, null, children) : React.createElement(ListGroup, null, children);
        };
        this.Item = (id) => {
            const { path } = this.state;
            const { rootOnly, grid, activeId } = this.props;
            const { Panel, Col, ListGroupItem } = this.context.theme;
            return !rootOnly ? (React.createElement(ListGroupItem, { key: id, className: path.length > 1 ? "not-root" : "" },
                path.length === 1 ? React.createElement("div", { className: `informal-group-image ${id}` }) : null,
                this.getLabel(id),
                this.getButtonGroup(id))) : (React.createElement(Col, Object.assign({ key: id }, grid),
                React.createElement(Panel, { onClick: this.onSelected(id), variant: id === activeId ? "primary" : undefined },
                    React.createElement(Panel.Heading, null, this.getLabel(id)),
                    React.createElement(Panel.Body, null,
                        React.createElement("div", { className: `informal-group-image ${id}` })))));
        };
        this.state = { path: [undefined] };
    }
    componentDidMount() {
        this.mounted = true;
        getInformalGroups(this.props.formContext.apiClient).then(state => {
            if (!this.mounted)
                return;
            this.setState(Object.assign(Object.assign({}, state), { root: state.informalTaxonGroups }));
        });
    }
    UNSAFE_componentWillReceiveProps(props) {
        if (this.props.lang === props.lang)
            return;
        getInformalGroups(this.props.formContext.apiClient).then(state => {
            if (!this.mounted)
                return;
            this.setState(Object.assign(Object.assign({}, state), { root: state.informalTaxonGroups }));
        });
    }
    componentWillUnmount() {
        this.mounted = false;
    }
    render() {
        const { path, informalTaxonGroupsById, informalTaxonGroups } = this.state;
        const { rootOnly } = this.props;
        const { translations } = this.props.formContext;
        const { Container, GroupsContainer, Item } = this;
        const { Breadcrumb } = this.context.theme;
        return (React.createElement(Container, null,
            !rootOnly && (React.createElement(Breadcrumb, null, path.map(id => React.createElement(Breadcrumb.Item, { key: id === undefined ? "root" : id, onClick: this.onSubgroupSelected(id) }, id === undefined ? translations.All : informalTaxonGroupsById[id].name)))),
            informalTaxonGroups
                ? React.createElement(GroupsContainer, null, Object.keys(informalTaxonGroups).map(Item))
                : React.createElement(react_spinner_1.default, null)));
    }
}
exports.InformalTaxonGroupChooser = InformalTaxonGroupChooser;
InformalTaxonGroupChooser.contextType = ReactContext_1.default;
InformalTaxonGroupChooser.propTypes = {
    onSelected: PropTypes.func.isRequired,
    formContext: PropTypes.object.isRequired
};
