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);
};
import React from 'react';
import { connect } from 'react-redux';
import styled from 'react-emotion';
import Canvas from './Canvas';
import { resolveBoardClass, resolveComponentClass, getCompatibleComponents, getCompatiblePorts, getConnectorPosition, getPortPosition, generateInstanceName } from '../lib/hardware';
import { updateComponents } from '../actions/hardware';
var Container = styled.div(templateObject_1 || (templateObject_1 = __makeTemplateObject(["\n  display: flex;\n  flex: 1;\n  overflow: hidden;\n"], ["\n  display: flex;\n  flex: 1;\n  overflow: hidden;\n"])));
var Toolbar = styled.div(templateObject_2 || (templateObject_2 = __makeTemplateObject(["\n  width: 300px;\n  background-color: #fafafa;\n  border-right: 1px solid rgba(0, 0, 0, 0.15);\n  z-index: 2;\n"], ["\n  width: 300px;\n  background-color: #fafafa;\n  border-right: 1px solid rgba(0, 0, 0, 0.15);\n  z-index: 2;\n"])));
var CanvasWrap = styled.div(templateObject_3 || (templateObject_3 = __makeTemplateObject(["\n  flex: 1;\n  display: flex;\n  position: relative;\n"], ["\n  flex: 1;\n  display: flex;\n  position: relative;\n"])));
var Board = styled.div(templateObject_4 || (templateObject_4 = __makeTemplateObject(["\n  position: absolute;\n  width: ", "px;\n  height: ", "px;\n  transform: translate(\n    ", "px,\n    ", "px\n  );\n  background: url(", ");\n  background-size: contain;\n"], ["\n  position: absolute;\n  width: ", "px;\n  height: ", "px;\n  transform: translate(\n    ", "px,\n    ", "px\n  );\n  background: url(", ");\n  background-size: contain;\n"])), function (props) { return props.image.width; }, function (props) { return props.image.height; }, function (props) { return 0 - props.image.width / 2; }, function (props) { return 0 - props.image.height / 2; }, function (props) { return props.image.url; });
var Component = styled.div(templateObject_5 || (templateObject_5 = __makeTemplateObject(["\n  position: absolute;\n  width: ", "px;\n  height: ", "px;\n  background: url(", ");\n  background-size: contain;\n"], ["\n  position: absolute;\n  width: ", "px;\n  height: ", "px;\n  background: url(", ");\n  background-size: contain;\n"])), function (props) { return props.image.width; }, function (props) { return props.image.height; }, function (props) { return props.image.url; });
var ToolbarComponent = styled(Component)(templateObject_6 || (templateObject_6 = __makeTemplateObject(["\n  position: relative;\n"], ["\n  position: relative;\n"])));
var ComponentWrap = styled.div(templateObject_7 || (templateObject_7 = __makeTemplateObject(["\n  position: relative;\n"], ["\n  position: relative;\n"])));
var Connector = styled.div(templateObject_8 || (templateObject_8 = __makeTemplateObject(["\n  border-radius: 100%;\n  width: 14px;\n  height: 14px;\n  background-color: #f1c933;\n  border: 1px solid #f19833;\n  position: absolute;\n  margin: -8px;\n  left: ", "%;\n  top: ", "%;\n\n  &:hover {\n    background-color: #f19833;\n  }\n"], ["\n  border-radius: 100%;\n  width: 14px;\n  height: 14px;\n  background-color: #f1c933;\n  border: 1px solid #f19833;\n  position: absolute;\n  margin: -8px;\n  left: ", "%;\n  top: ", "%;\n\n  &:hover {\n    background-color: #f19833;\n  }\n"])), function (props) { return props.x * 100; }, function (props) { return props.y * 100; });
var Port = styled.div(templateObject_9 || (templateObject_9 = __makeTemplateObject(["\n  width: 14px;\n  height: 14px;\n  background-color: #f1c933;\n  border: 1px solid #f19833;\n  position: absolute;\n  margin: -8px;\n  left: ", "%;\n  top: ", "%;\n\n  &:hover {\n    background-color: #f19833;\n  }\n"], ["\n  width: 14px;\n  height: 14px;\n  background-color: #f1c933;\n  border: 1px solid #f19833;\n  position: absolute;\n  margin: -8px;\n  left: ", "%;\n  top: ", "%;\n\n  &:hover {\n    background-color: #f19833;\n  }\n"])), function (props) { return props.x * 100; }, function (props) { return props.y * 100; });
var ConnectionEditor = /** @class */ (function (_super) {
    __extends(ConnectionEditor, _super);
    function ConnectionEditor() {
        var _this = _super !== null && _super.apply(this, arguments) || this;
        _this.state = {
            draggingComponent: null,
            dragOffsetX: 0,
            dragOffsetY: 0,
            draggingConnection: null,
            compatiblePorts: [],
        };
        _this.canvas = React.createRef();
        _this.onDragItem = function (x, y) {
            _this.setState(function (prevState) { return (__assign({}, prevState, { draggingComponent: __assign({}, prevState.draggingComponent, { x: x,
                    y: y }) })); });
        };
        _this.onDragItemStop = function (x, y) {
            var _a = _this.props, components = _a.components, updateComponents = _a.updateComponents;
            var draggingComponent = _this.state.draggingComponent;
            _this.setState(function (prevState) { return (__assign({}, prevState, { draggingComponent: null })); });
            updateComponents(components.concat([draggingComponent]));
        };
        _this.onDragConnection = function (x, y) {
            _this.setState(function (prevState) { return (__assign({}, prevState, { draggingConnection: __assign({}, prevState.draggingConnection, { x2: x, y2: y }) })); });
        };
        _this.onDragConnectionStop = function (x, y) {
            var _a = _this.props, components = _a.components, updateComponents = _a.updateComponents;
            var draggingConnection = _this.state.draggingConnection;
            var component = draggingConnection.component, connector = draggingConnection.connector, port = draggingConnection.port;
            if (port) {
                var _b = component.connections, connections = _b === void 0 ? [] : _b;
                var updatedComponent_1 = __assign({}, component, { connections: connections.concat([{ connector: connector, port: port }]) });
                updateComponents(components.map(function (c) { return (c === component ? updatedComponent_1 : c); }));
            }
            _this.setState(function (prevState) { return (__assign({}, prevState, { draggingConnection: null, compatiblePorts: [] })); });
        };
        _this.onPortMouseOver = function (port) {
            _this.setState(function (prevState) { return (__assign({}, prevState, { draggingConnection: __assign({}, prevState.draggingConnection, { port: port.name }) })); });
        };
        _this.onPortMouseOut = function () {
            _this.setState(function (prevState) { return (__assign({}, prevState, { draggingConnection: __assign({}, prevState.draggingConnection, { port: null }) })); });
        };
        _this.renderComponent = function (component, isDragging) {
            var board = _this.props.board;
            if (component === board) {
                var _a = _this.state, draggingConnection = _a.draggingConnection, compatiblePorts = _a.compatiblePorts;
                var boardClass = resolveBoardClass(board.className);
                var image = boardClass.image;
                return (React.createElement(Board, { image: image }, draggingConnection &&
                    compatiblePorts.map(function (port) { return (React.createElement(Port, { onMouseOver: function () { return _this.onPortMouseOver(port); }, onMouseOut: _this.onPortMouseOut, key: port.name, x: port.x, y: port.y })); })));
            }
            else {
                var componentClass = resolveComponentClass(component.className);
                var image = componentClass.image, _b = componentClass.connectors, connectors = _b === void 0 ? [] : _b;
                return (React.createElement(Component, { image: image, onMouseDown: function (e) { return _this.onComponentMouseDown(e, component); } }, connectors.map(function (connector) { return (React.createElement(Connector, { x: connector.x, y: connector.y, key: connector.name, onMouseDown: function (e) {
                        return _this.onConnectorMouseDown(e, component, connector);
                    } })); })));
            }
        };
        return _this;
    }
    ConnectionEditor.prototype.onToolbarComponentMouseDown = function (e, componentClass) {
        var components = this.props.components;
        var newComponent = {
            name: generateInstanceName(componentClass, components),
            className: componentClass.name,
        };
        this.startDraggingComponent(e, newComponent);
    };
    ConnectionEditor.prototype.onComponentMouseDown = function (e, component) {
        var _a = this.props, components = _a.components, updateComponents = _a.updateComponents;
        var newComponents = components.filter(function (c) { return c !== component; });
        updateComponents(newComponents);
        this.startDraggingComponent(e, component);
    };
    ConnectionEditor.prototype.onConnectorMouseDown = function (e, component, connector) {
        e.stopPropagation();
        var board = this.props.board;
        var _a = getConnectorPosition(component, connector.name), x = _a.x, y = _a.y;
        this.setState(function (prevState) { return ({
            draggingConnection: {
                component: component,
                connector: connector.name,
                x2: x,
                y2: y,
            },
            compatiblePorts: getCompatiblePorts(board, connector.type),
        }); });
    };
    ConnectionEditor.prototype.startDraggingComponent = function (e, component) {
        var _a = e.currentTarget.getBoundingClientRect(), elementX = _a.x, elementY = _a.y;
        var dragOffsetX = e.clientX - elementX;
        var dragOffsetY = e.clientY - elementY;
        var _b = this.canvas.current.getItemPosition(e, dragOffsetX, dragOffsetY), x = _b.x, y = _b.y;
        this.setState(function (prevState) { return (__assign({}, prevState, { draggingComponent: __assign({}, component, { x: x, y: y }), dragOffsetX: dragOffsetX,
            dragOffsetY: dragOffsetY })); });
    };
    ConnectionEditor.prototype.render = function () {
        var _this = this;
        var _a = this.state, draggingComponent = _a.draggingComponent, draggingConnection = _a.draggingConnection, dragOffsetX = _a.dragOffsetX, dragOffsetY = _a.dragOffsetY;
        var _b = this.props, board = _b.board, components = _b.components;
        var boardClass = resolveBoardClass(board.className);
        var compatibleComponents = getCompatibleComponents(boardClass).filter(function (_a) {
            var image = _a.image;
            return image;
        });
        var canvasItems = [board].concat(components);
        var allConnections = [];
        components.forEach(function (component) {
            var _a = component.connections, connections = _a === void 0 ? [] : _a;
            connections.forEach(function (_a) {
                var connector = _a.connector, port = _a.port;
                var _b = getConnectorPosition(component, connector), x1 = _b.x, y1 = _b.y;
                var _c = getPortPosition(board, port), x2 = _c.x, y2 = _c.y;
                allConnections.push({ x1: x1, y1: y1, x2: x2, y2: y2 });
            });
        });
        if (draggingConnection) {
            var component = draggingConnection.component, connector = draggingConnection.connector, x2 = draggingConnection.x2, y2 = draggingConnection.y2;
            var _c = getConnectorPosition(component, connector), x1 = _c.x, y1 = _c.y;
            allConnections.push({ x1: x1, y1: y1, x2: x2, y2: y2 });
        }
        return (React.createElement(Container, null,
            React.createElement(Toolbar, null, compatibleComponents
                .filter(function (componentClass) { return componentClass.image; })
                .map(function (componentClass) { return (React.createElement(ToolbarComponent, { image: componentClass.image, key: componentClass.name, onMouseDown: function (e) {
                    return _this.onToolbarComponentMouseDown(e, componentClass);
                } })); })),
            React.createElement(Canvas, { ref: this.canvas, items: canvasItems, renderItem: this.renderComponent, dragOffsetX: dragOffsetX, dragOffsetY: dragOffsetY, draggingItem: draggingComponent, onDragItem: this.onDragItem, onDragItemStop: this.onDragItemStop, draggingConnection: draggingConnection, onDragConnection: this.onDragConnection, onDragConnectionStop: this.onDragConnectionStop, connections: allConnections })));
    };
    return ConnectionEditor;
}(React.Component));
var mapStateToProps = function (_a) {
    var hardware = _a.hardware;
    return ({
        board: hardware.board,
        components: hardware.components,
    });
};
var mapDispatchToProps = function (dispatch) { return ({
    updateComponents: function (components) { return dispatch(updateComponents(components)); },
}); };
export default connect(mapStateToProps, mapDispatchToProps)(ConnectionEditor);
var templateObject_1, templateObject_2, templateObject_3, templateObject_4, templateObject_5, templateObject_6, templateObject_7, templateObject_8, templateObject_9;
//# sourceMappingURL=ConnectionEditor.js.map