var __makeTemplateObject = (this && this.__makeTemplateObject) || function (cooked, raw) {
    if (Object.defineProperty) { Object.defineProperty(cooked, "raw", { value: raw }); } else { cooked.raw = raw; }
    return cooked;
};
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);
};
var __rest = (this && this.__rest) || function (s, e) {
    var t = {};
    for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
        t[p] = s[p];
    if (s != null && typeof Object.getOwnPropertySymbols === "function")
        for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) if (e.indexOf(p[i]) < 0)
            t[p[i]] = s[p[i]];
    return t;
};
import React from 'react';
import { connect } from 'react-redux';
import styled, { css } from 'react-emotion';
import { DragDropContext, Droppable, Draggable } from 'react-beautiful-dnd';
import { shadow } from '../../base-styles';
import { Icon } from '@bitbloq/ui';
import { selectObject, deselectObject, createObject, updateObject, } from '../../actions/threed';
import { getObjects, getSelectedObjects } from '../../reducers/threed/';
import config from '../../config/threed';
var Container = styled.div(templateObject_1 || (templateObject_1 = __makeTemplateObject(["\n  width: 180px;\n  display: flex;\n  flex-direction: column;\n  border-right: 1px solid #cfcfcf;\n"], ["\n  width: 180px;\n  display: flex;\n  flex-direction: column;\n  border-right: 1px solid #cfcfcf;\n"])));
var Tree = styled.div(templateObject_2 || (templateObject_2 = __makeTemplateObject(["\n  flex: 1;\n  display: flex;\n  overflow-y: auto;\n  padding: 20px 0px;\n"], ["\n  flex: 1;\n  display: flex;\n  overflow-y: auto;\n  padding: 20px 0px;\n"])));
var ObjectList = styled.ul(templateObject_3 || (templateObject_3 = __makeTemplateObject(["\n  width: 100%;\n"], ["\n  width: 100%;\n"])));
var ObjectItem = styled.li(templateObject_4 || (templateObject_4 = __makeTemplateObject(["\n  width: 100%;\n"], ["\n  width: 100%;\n"])));
var ObjectName = styled.div(templateObject_6 || (templateObject_6 = __makeTemplateObject(["\n  padding: 0px 18px 0px 8px;\n  cursor: pointer;\n  display: flex;\n  align-items: center;\n  border-color: #eee;\n  border-style: solid;\n  border-width: 1px 0px 1px 0px;\n  background-color: white;\n  font-size: 13px;\n  height: 30px;\n  margin-bottom: -1px;\n\n  ", ";\n\n  span {\n    flex: 1;\n    margin-left: 4px;\n  }\n\n  img {\n    width: 24px;\n  }\n"], ["\n  padding: 0px 18px 0px 8px;\n  cursor: pointer;\n  display: flex;\n  align-items: center;\n  border-color: #eee;\n  border-style: solid;\n  border-width: 1px 0px 1px 0px;\n  background-color: white;\n  font-size: 13px;\n  height: 30px;\n  margin-bottom: -1px;\n\n  ",
    ";\n\n  span {\n    flex: 1;\n    margin-left: 4px;\n  }\n\n  img {\n    width: 24px;\n  }\n"])), function (props) {
    return props.isSelected && css(templateObject_5 || (templateObject_5 = __makeTemplateObject(["\n      color: white;\n      background-color: #4dc3ff;\n      border-color: inherit;\n    "], ["\n      color: white;\n      background-color: #4dc3ff;\n      border-color: inherit;\n    "])));
});
var DragHandle = styled.div(templateObject_7 || (templateObject_7 = __makeTemplateObject(["\n  margin-right: ", "px;\n  svg {\n    width: 13px;\n  }\n"], ["\n  margin-right: ", "px;\n  svg {\n    width: 13px;\n  }\n"])), function (props) { return 4 + 12 * (props.depth || 0); });
var AddButton = styled.div(templateObject_9 || (templateObject_9 = __makeTemplateObject(["\n  display: flex;\n  justify-content: center;\n  align-items: center;\n  height: 50px;\n  background-color: #ebebeb;\n  font-size: 13px;\n  font-weight: bold;\n  cursor: pointer;\n  position: relative;\n  border-bottom: 1px solid #cfcfcf;\n  z-index: 2;\n\n  ", ";\n"], ["\n  display: flex;\n  justify-content: center;\n  align-items: center;\n  height: 50px;\n  background-color: #ebebeb;\n  font-size: 13px;\n  font-weight: bold;\n  cursor: pointer;\n  position: relative;\n  border-bottom: 1px solid #cfcfcf;\n  z-index: 2;\n\n  ",
    ";\n"])), function (props) {
    return props.open && css(templateObject_8 || (templateObject_8 = __makeTemplateObject(["\n      ", ";\n    "], ["\n      ", ";\n    "])), shadow);
});
var AddDropdown = styled.div(templateObject_11 || (templateObject_11 = __makeTemplateObject(["\n  background-color: white;\n  color: #333;\n  position: absolute;\n  top: 51px;\n  left: 0px;\n  right: 0px;\n  transition: opacity 0.3s;\n  ", " border-radius: 0px 0px 4px 4px;\n  opacity: 0;\n  display: none;\n\n  ", ";\n"], ["\n  background-color: white;\n  color: #333;\n  position: absolute;\n  top: 51px;\n  left: 0px;\n  right: 0px;\n  transition: opacity 0.3s;\n  ", " border-radius: 0px 0px 4px 4px;\n  opacity: 0;\n  display: none;\n\n  ",
    ";\n"])), shadow, function (props) {
    return props.open && css(templateObject_10 || (templateObject_10 = __makeTemplateObject(["\n      opacity: 1;\n      display: block;\n    "], ["\n      opacity: 1;\n      display: block;\n    "])));
});
var AddDropdownItem = styled.div(templateObject_12 || (templateObject_12 = __makeTemplateObject(["\n  display: flex;\n  align-items: center;\n  padding: 0px 20px;\n  height: 42px;\n  cursor: pointer;\n  font-size: 14px;\n  font-weight: normal;\n\n  &:hover {\n    background-color: #ebebeb;\n  }\n\n  svg {\n    height: auto;\n    width: 24px;\n    margin-right: 10px;\n  }\n"], ["\n  display: flex;\n  align-items: center;\n  padding: 0px 20px;\n  height: 42px;\n  cursor: pointer;\n  font-size: 14px;\n  font-weight: normal;\n\n  &:hover {\n    background-color: #ebebeb;\n  }\n\n  svg {\n    height: auto;\n    width: 24px;\n    margin-right: 10px;\n  }\n"])));
var CollapseButton = styled.div(templateObject_14 || (templateObject_14 = __makeTemplateObject(["\n  display: flex;\n\n  svg {\n    width: 10px;\n  }\n\n  ", ";\n"], ["\n  display: flex;\n\n  svg {\n    width: 10px;\n  }\n\n  ",
    ";\n"])), function (props) {
    return props.collapsed && css(templateObject_13 || (templateObject_13 = __makeTemplateObject(["\n      svg {\n        transform: rotate(-90deg);\n      }\n    "], ["\n      svg {\n        transform: rotate(-90deg);\n      }\n    "])));
});
var ObjectTypeIcon = styled.div(templateObject_15 || (templateObject_15 = __makeTemplateObject(["\n  svg {\n    width: 12px;\n  }\n"], ["\n  svg {\n    width: 12px;\n  }\n"])));
var ObjectTree = /** @class */ (function (_super) {
    __extends(ObjectTree, _super);
    function ObjectTree() {
        var _this = _super !== null && _super.apply(this, arguments) || this;
        _this.state = {
            addDropDownOpen: false,
            collapsedItems: [],
        };
        _this.onBodyClick = function () {
            _this.setState({ addDropDownOpen: false });
        };
        _this.onCollapseClick = function (e, object) {
            e.stopPropagation();
            _this.setState(function (_a) {
                var collapsedItems = _a.collapsedItems, state = __rest(_a, ["collapsedItems"]);
                return (__assign({}, state, { collapsedItems: collapsedItems.includes(object.id)
                        ? collapsedItems.filter(function (id) { return id !== object.id; })
                        : collapsedItems.concat([object.id]) }));
            });
        };
        return _this;
    }
    ObjectTree.prototype.componentDidMount = function () {
        document.body.addEventListener('click', this.onBodyClick);
    };
    ObjectTree.prototype.componentWillUnmount = function () {
        document.body.removeEventListener('click', this.onBodyClick);
    };
    ObjectTree.prototype.onAddObject = function (typeConfig) {
        var advancedMode = this.props.advancedMode;
        this.setState({ addDropDownOpen: false });
        var object = __assign({}, typeConfig.create(), { operations: config.defaultOperations(advancedMode) });
        this.props.createObject(object);
    };
    ObjectTree.prototype.onDragEnd = function (result) {
        var destination = result.destination, source = result.source, droppableId = result.droppableId, draggableId = result.draggableId;
        var _a = this.props, objects = _a.objects, updateObject = _a.updateObject;
        if (!destination || !destination.droppableId)
            return;
        var parent = objects.find(function (_a) {
            var id = _a.id;
            return id === destination.droppableId;
        });
        if (!parent || !parent.children)
            return;
        var child = parent.children.find(function (_a) {
            var id = _a.id;
            return id === draggableId;
        });
        if (!child)
            return;
        var newChildren = parent.children.slice();
        newChildren.splice(source.index, 1);
        newChildren.splice(destination.index, 0, child);
        this.props.updateObject(__assign({}, parent, { children: newChildren }));
    };
    ObjectTree.prototype.renderObjectItem = function (object, index, depth, parent) {
        var _this = this;
        var _a = this.props, topObjects = _a.objects, selectedObjects = _a.selectedObjects, selectObject = _a.selectObject, deselectObject = _a.deselectObject, controlPressed = _a.controlPressed, shiftPressed = _a.shiftPressed;
        var collapsedItems = this.state.collapsedItems;
        var isSelected = selectedObjects.includes(object);
        var isTop = topObjects.includes(object);
        var isSelectedTop = selectedObjects.length > 0 && topObjects.includes(selectedObjects[0]);
        var _b = object.children, children = _b === void 0 ? [] : _b, id = object.id;
        var isCollapsed = collapsedItems.includes(id);
        var icon;
        if (children.length) {
            var typeConfig = config.objectTypes.find(function (t) { return t.name === object.type; }) || {};
            icon = typeConfig.icon;
        }
        return (React.createElement(Draggable, { draggableId: id, index: index, key: id }, function (provided, snapshot) { return (React.createElement(ObjectItem, __assign({}, provided.draggableProps, { innerRef: provided.innerRef }),
            React.createElement(ObjectName, { isFirstSelected: selectedObjects.indexOf(object) === 0, isSelected: isSelected, onClick: function () {
                    if (isTop &&
                        isSelectedTop &&
                        (controlPressed || shiftPressed)) {
                        if (isSelected) {
                            deselectObject(object);
                        }
                        else {
                            selectObject(object, true);
                        }
                    }
                    else {
                        if (isSelected && selectedObjects.length === 1) {
                            deselectObject(object);
                        }
                        else {
                            selectObject(object);
                        }
                    }
                } },
                React.createElement(DragHandle, __assign({}, provided.dragHandleProps, { depth: depth }),
                    React.createElement(Icon, { name: "drag" })),
                children.length > 0 && (React.createElement(CollapseButton, { collapsed: isCollapsed, onClick: function (e) { return _this.onCollapseClick(e, object); } },
                    React.createElement(Icon, { name: "angle" }))),
                React.createElement("span", null, object.viewOptions.name || object.type),
                icon &&
                    React.createElement(ObjectTypeIcon, null, icon)),
            !isCollapsed && _this.renderObjectList(children, depth + 1, object))); }));
    };
    ObjectTree.prototype.renderObjectList = function (objects, depth, parent) {
        var _this = this;
        if (depth === void 0) { depth = 0; }
        if (objects && objects.length) {
            var parentId = parent ? parent.id : 'root';
            return (React.createElement(Droppable, { droppableId: parentId, type: parentId }, function (provided) { return (React.createElement(ObjectList, __assign({ innerRef: provided.innerRef }, provided.droppableProps),
                objects.map(function (object, index) {
                    return _this.renderObjectItem(object, index, depth, parent);
                }),
                provided.placeholder)); }));
        }
    };
    ObjectTree.prototype.render = function () {
        var _this = this;
        var addDropDownOpen = this.state.addDropDownOpen;
        var objects = this.props.objects;
        return (React.createElement(DragDropContext, { onDragEnd: function (result) { return _this.onDragEnd(result); } },
            React.createElement(Container, null,
                React.createElement(AddButton, { onClick: function () { return _this.setState({ addDropDownOpen: true }); }, open: addDropDownOpen },
                    React.createElement("div", null, "+ Add object"),
                    React.createElement(AddDropdown, { open: addDropDownOpen }, config.objectTypes.map(function (typeConfig) {
                        return typeConfig.create && (React.createElement(AddDropdownItem, { key: typeConfig.name, onClick: function (e) {
                                e.stopPropagation();
                                _this.onAddObject(typeConfig);
                            } },
                            typeConfig.icon,
                            React.createElement("div", null, typeConfig.label)));
                    }))),
                React.createElement(Tree, null, this.renderObjectList(objects)))));
    };
    return ObjectTree;
}(React.Component));
var mapStateToProps = function (_a) {
    var ui = _a.ui, threed = _a.threed;
    return ({
        objects: getObjects(threed),
        selectedObjects: getSelectedObjects(threed),
        controlPressed: ui.controlPressed,
        shiftPressed: ui.shiftPressed,
        advancedMode: threed.ui.advancedMode,
    });
};
var mapDispatchToProps = function (dispatch) { return ({
    selectObject: function (object, addToSelection) {
        return dispatch(selectObject(object, addToSelection));
    },
    deselectObject: function (object) { return dispatch(deselectObject(object)); },
    createObject: function (object) { return dispatch(createObject(object)); },
    updateObject: function (object) { return dispatch(updateObject(object)); },
}); };
export default connect(mapStateToProps, mapDispatchToProps)(ObjectTree);
var templateObject_1, templateObject_2, templateObject_3, templateObject_4, templateObject_5, templateObject_6, templateObject_7, templateObject_8, templateObject_9, templateObject_10, templateObject_11, templateObject_12, templateObject_13, templateObject_14, templateObject_15;
//# sourceMappingURL=ObjectTree.js.map