"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.MINIMAP_HEIGHT = exports.MINIMAP_WIDTH = exports.DEFAULT_STYLE = exports.getMinimapSize = void 0;
const namespaceURI_1 = require("../../../../../client/component/namespaceURI");
const element_1 = require("../../../../../client/element");
const id_1 = require("../../../../../client/id");
const parentElement_1 = require("../../../../../client/platform/web/parentElement");
const theme_1 = require("../../../../../client/theme");
const geometry_1 = require("../../../../../client/util/geometry");
const userSelect_1 = require("../../../../../client/util/style/userSelect");
const object_1 = require("../../../../../util/object");
const Component_1 = __importDefault(require("../../Div/Component"));
const Component_2 = __importDefault(require("../../svg/Group/Component"));
const Component_3 = __importDefault(require("../../svg/Path/Component"));
const Component_4 = __importDefault(require("../../svg/SVG/Component"));
const MINIMAP_AREA = 180 * 180;
const getMinimapSize = ($width, $height) => {
    const screen_ratio = $width / $height;
    const width = Math.sqrt(MINIMAP_AREA * screen_ratio);
    const height = Math.sqrt(MINIMAP_AREA / screen_ratio);
    return { width, height };
};
exports.getMinimapSize = getMinimapSize;
exports.DEFAULT_STYLE = {
    ...(0, userSelect_1.userSelect)('none'),
};
exports.MINIMAP_WIDTH = 200;
exports.MINIMAP_HEIGHT = 150;
class Minimap extends element_1.Element {
    constructor($props, $system) {
        super($props, $system);
        this._node_component = {};
        this._link_el = {};
        this._min_x = 1000000;
        this._max_x = -1000000;
        this._min_y = 1000000;
        this._max_y = -1000000;
        const { style, width, height } = $props;
        const root = new Component_1.default({
            className: 'minimap-root',
            style: {
                width: '100%',
                height: '100%',
            },
        }, this.$system);
        root.preventDefault('mousedown');
        root.preventDefault('touchdown');
        const map_graph = new Component_2.default({ className: 'minimap-graph' }, this.$system);
        this._map_graph = map_graph;
        const map_children = new Component_2.default({ className: 'minimap-children' }, this.$system);
        this._map_children = map_children;
        const svg = new Component_4.default({
            className: 'minimap',
            attr: {
                width: `${width}`,
                height: `${height}`,
                tabindex: `${-1}`,
            },
            style: {
                ...exports.DEFAULT_STYLE,
                ...style,
            },
            viewBox: '0 0 0 0',
        }, this.$system);
        this._map_el = svg;
        this.tick();
        const $element = (0, parentElement_1.parentElement)($system);
        this.$element = $element;
        this.$slot = map_children.$slot;
        this.$unbundled = false;
        this.$primitive = true;
        this.setSubComponents({
            root,
            svg,
            map_graph,
            map_children,
        });
        root.registerParentRoot(svg);
        this.registerRoot(root);
        svg.registerParentRoot(map_graph);
        svg.registerParentRoot(map_children);
        svg.$element.onfocus = () => {
            // console.log('Minimap', 'onFocus')
        };
    }
    onPropChanged(prop, current) {
        // console.log('Minimap', 'onPropChanged', prop, current)
        if (prop === 'style') {
            this._map_el.setProp('style', {
                ...exports.DEFAULT_STYLE,
                ...current,
            });
        }
    }
    tick() {
        const { nodes = {}, links = {}, padding = 0 } = this.$props;
        for (const node_id in this._node_component) {
            if (!nodes[node_id]) {
                const node_el = this._node_component[node_id];
                this._map_graph.$element.removeChild(node_el.$element);
                delete this._node_component[node_id];
            }
        }
        for (const link_id in this._link_el) {
            if (!links[link_id]) {
                const link_el = this._link_el[link_id];
                this._map_graph.$element.removeChild(link_el);
                delete this._link_el[link_id];
            }
        }
        if ((0, object_1.isEmptyObject)(nodes)) {
            return;
        }
        let min_x = Number.MAX_SAFE_INTEGER;
        let max_x = Number.MIN_SAFE_INTEGER;
        let min_y = Number.MAX_SAFE_INTEGER;
        let max_y = Number.MIN_SAFE_INTEGER;
        for (const node_id in nodes) {
            const node = nodes[node_id];
            const { x, y, width, height, r, shape } = node;
            min_x = Math.min(min_x, x - width / 2);
            max_x = Math.max(max_x, x + width / 2);
            min_y = Math.min(min_y, y - height / 2);
            max_y = Math.max(max_y, y + height / 2);
            let node_component = this._node_component[node_id];
            if (!node_component) {
                node_component = new Component_3.default({
                    style: {
                        fill: theme_1.COLOR_NONE,
                        pointerEvents: 'none',
                        strokeWidth: 'inherit',
                    },
                    attr: {
                        'stroke-linecap': 'normal',
                    },
                }, this.$system);
                this._node_component[node_id] = node_component;
                this._map_graph.appendChild(node_component);
            }
            const d = shape === 'circle'
                ? (0, geometry_1.describeCircle)(x, y, r)
                : (0, geometry_1.describeRect)(x - width / 2, y - height / 2, width, height);
            node_component.setProp('d', d);
        }
        for (const link_id in links) {
            const { source, target } = (0, id_1.segmentLinkId)(link_id);
            if (source === target) {
                continue;
            }
            let link_el = this._link_el[link_id];
            if (!link_el) {
                link_el = this.$system.api.document.createElementNS(namespaceURI_1.namespaceURI, 'line');
                link_el.style.pointerEvents = 'none';
                this._link_el[link_id] = link_el;
                this._map_graph.$element.appendChild(link_el);
            }
            const sourceNode = nodes[source];
            const targetNode = nodes[target];
            const { x: x0, y: y0 } = sourceNode;
            const { x: x1, y: y1 } = targetNode;
            const u = (0, geometry_1.unitVector)(x0, y0, x1, y1);
            const nu = (0, geometry_1.oppositeVector)(u);
            const { x: _x0, y: _y0 } = (0, geometry_1.pointInNode)(sourceNode, u);
            const { x: _x1, y: _y1 } = (0, geometry_1.pointInNode)(targetNode, nu);
            link_el.setAttribute('x1', `${_x0}`);
            link_el.setAttribute('y1', `${_y0}`);
            link_el.setAttribute('x2', `${_x1}`);
            link_el.setAttribute('y2', `${_y1}`);
        }
        min_x -= padding;
        min_y -= padding;
        max_x += padding;
        max_y += padding;
        const width = max_x - min_x;
        const height = max_y - min_y;
        this._min_x = min_x;
        this._min_y = min_y;
        this._max_x = max_x;
        this._max_y = max_y;
        this._width = width;
        this._height = height;
        const strokeWidth = width / exports.MINIMAP_WIDTH + height / exports.MINIMAP_HEIGHT;
        this._map_el.$element.style.strokeWidth = `${strokeWidth}px`;
        this._map_el.setProp('viewBox', `${min_x} ${min_y} ${width} ${height}`);
    }
}
exports.default = Minimap;
//# sourceMappingURL=Component.js.map