"use strict";
var __extends = (this && this.__extends) || (function () {
    var 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 function (d, b) {
        extendStatics(d, b);
        function __() { this.constructor = d; }
        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
    };
})();
Object.defineProperty(exports, "__esModule", { value: true });
// tslint:disable:jsx-no-multiline-js
var React = require("react");
var _ = require("lodash");
var react_redux_1 = require("react-redux");
var core_1 = require("@jsonforms/core");
var ObjectListItem_1 = require("./ObjectListItem");
var react_dnd_1 = require("react-dnd");
var dnd_util_1 = require("./dnd.util");
var container_util_1 = require("../helpers/container.util");
var styles_1 = require("@material-ui/core/styles");
var recompose_1 = require("recompose");
/**
 * Expands the given data array by expanding every element.
 * If the parent data containing the array is provided,
 * a suitable delete function for the expanded elements is created.
 *
 * @param data the array to expand
 * @param {@link Property} property It describes a single property.
 *                                  It is used to match a given data element with a schema by searching
 *                                  a list of properties.
 *
 * @param parentPath the instance path where data can be obtained from
 */
exports.ExpandArray = function (_a) {
    var rootData = _a.rootData, containmentProps = _a.containmentProps, path = _a.path, selection = _a.selection, handlers = _a.handlers, filterPredicate = _a.filterPredicate, labelProvider = _a.labelProvider, imageProvider = _a.imageProvider;
    var data = core_1.resolveData(rootData, path);
    if (data === undefined || data === null) {
        // return 'No data';
        return '';
    }
    return (data.map(function (element, index) {
        var composedPath = core_1.Paths.compose(path, index.toString());
        var property = container_util_1.matchContainerProperty(element, containmentProps, filterPredicate);
        if (property === undefined || data === null) {
            return React.createElement("li", null, "No ContainmentProperty");
        }
        return (React.createElement(ObjectListItem_1.default, { key: composedPath, path: composedPath, schema: property.schema, selection: selection, handlers: handlers, parentProperties: containmentProps, filterPredicate: filterPredicate, labelProvider: labelProvider, imageProvider: imageProvider }));
    }));
};
var styles = function () { return ({
    currentTarget: {
        borderWidth: 'medium'
    },
    validTarget: {
        borderStyle: 'dashed',
        borderWidth: 'thin',
        borderColor: 'rgb(88, 199, 23)',
        minHeight: '1em'
    },
    invalidTarget: {
        borderStyle: 'dashed',
        borderWidth: 'thin',
        borderColor: 'rgb(189, 0, 0)'
    }
}); };
var ExpandArrayContainer = /** @class */ (function (_super) {
    __extends(ExpandArrayContainer, _super);
    function ExpandArrayContainer(props) {
        var _this = _super.call(this, props) || this;
        _this.state = { setCss: false };
        return _this;
    }
    ExpandArrayContainer.prototype.componentWillReceiveProps = function (nextProps) {
        var _this = this;
        if (this.props.isDragging && !nextProps.isDragging) {
            this.setState({ setCss: false });
        }
        else if (!this.props.isDragging && nextProps.isDragging) {
            setTimeout(function () { return _this.setState({ setCss: true }); }, dnd_util_1.CSS_DELAY);
        }
    };
    ExpandArrayContainer.prototype.render = function () {
        var _a = this.props, rootData = _a.rootData, containmentProps = _a.containmentProps, path = _a.path, selection = _a.selection, handlers = _a.handlers, 
        // Drag and Drop Parameters
        connectDropTarget = _a.connectDropTarget, isOver = _a.isOver, validDropTarget = _a.validDropTarget, filterPredicate = _a.filterPredicate, labelProvider = _a.labelProvider, imageProvider = _a.imageProvider, classes = _a.classes;
        if (_.isEmpty(containmentProps)) {
            return undefined;
        }
        var className = '';
        // Only apply D&D CSS if the flag has been set
        if (this.state.setCss) {
            if (validDropTarget) {
                className = classes.validTarget;
                if (isOver) {
                    className = className + " " + classes.currentTarget;
                }
            }
            else if (isOver) {
                className = classes.invalidTarget + " " + classes.currentTarget;
            }
        }
        return connectDropTarget(React.createElement("ul", { key: _.head(containmentProps).property, className: className },
            React.createElement(exports.ExpandArray, { containmentProps: containmentProps, path: path, rootData: rootData, selection: selection, handlers: handlers, filterPredicate: filterPredicate, labelProvider: labelProvider, imageProvider: imageProvider })));
    };
    return ExpandArrayContainer;
}(React.Component));
var mapStateToProps = function (state) { return ({
    rootData: core_1.getData(state)
}); };
/**
 * Injects drag and drop related properties into an expanded array
 */
var collect = function (dndConnect, monitor) {
    return {
        connectDropTarget: dndConnect.dropTarget(),
        isOver: monitor.isOver({ shallow: true }),
        validDropTarget: monitor.canDrop(),
        isDragging: monitor.getItem() !== null
    };
};
/**
 * The drop target contract for an expanded array.
 * The specified methods are executed by React DnD when appropriate
 * (e.g. a draggable component hovers over an expanded array).
 */
var arrayDropTarget = {
    /**
     * Tests wether the currently dragged object list item can be dropped in this list
     * by checking whether the item's schema id matches with a containment property of this list.
     */
    canDrop: function (props, monitor) {
        return dnd_util_1.canDropDraggedItem(props.containmentProps, monitor.getItem());
    },
    /**
     * Called when an item was dropped at a valid location (canDrop() === true)
     * The calls also go up the chain when the drop occurred in a nested component.
     * The most nested one is called first, return results are available
     * from the before called component.
     */
    drop: function (props, monitor) {
        // drop was handled by a nested list
        if (monitor.didDrop()) {
            return monitor.getDropResult();
        }
        // TODO remove console.log
        console.log('valid drop of data at: ' + props.path);
        var dropInfo = {
            isHandled: true,
            move: true,
            moveTarget: core_1.Paths.compose(props.path, '0')
        };
        return dropInfo;
    }
};
var DnDExandArrayContainer = recompose_1.compose(styles_1.withStyles(styles, { name: 'ExpandArrayContainer' }), react_dnd_1.DropTarget(dnd_util_1.Types.TREE_DND, arrayDropTarget, collect))(ExpandArrayContainer);
exports.default = react_redux_1.connect(mapStateToProps, dnd_util_1.mapDispatchToTreeListProps)(DnDExandArrayContainer);
//# sourceMappingURL=ExpandArray.js.map