var _a;
import { __decorate } from "tslib";
/* eslint-disable @typescript-eslint/no-unused-vars */
/* eslint-disable class-methods-use-this */
import { html, LitElement, svg } from "lit";
import { property } from "lit/decorators.js";
import { styleMap } from "lit/directives/style-map.js";
import { AssociationAnchors } from "../lib/AssociationAnchors.js";
import { SelectionManager } from "../lib/SelectionManager.js";
import { ShapeArtist } from "../lib/ShapeArtist.js";
import { WorkspaceEdges } from "../lib/WorkspaceEdges.js";
import { WorkspaceGestures } from "../lib/WorkspaceGestures.js";
import { WorkspaceSizing } from "../lib/WorkspaceSizing.js";
import elementStyles from './WorkspaceStyles.js';
const defaultCanvasWidth = 3840;
const defaultCanvasHeight = 2160;
export const canvasRef = Symbol('canvasRef');
export const svgRef = Symbol('svgRef');
export const attributeTypeEditHandler = Symbol('attributeTypeEditHandler');
export const attributeTypeDropdownClosedHandler = Symbol('attributeTypeDropdownClosedHandler');
export const attributeTypeSelectHandler = Symbol('attributeTypeSelectHandler');
export const geometryChangeHandler = Symbol('geometryChangeHandler');
export const widthValue = Symbol('widthValue');
export const heightValue = Symbol('heightValue');
export const autoResizeValue = Symbol('autoResizeValue');
export const zoomValue = Symbol('zoomValue');
export const notifyZoom = Symbol('notifyZoom');
export const zoomTimeout = Symbol('zoomTimeout');
/**
 * @fires positionchange
 */
export default class VizWorkspaceElement extends LitElement {
    static get styles() {
        return [elementStyles];
    }
    /**
     * The zoom level of the current visualization
     * @attribute
     */
    get zoom() {
        return this[zoomValue] || 0;
    }
    set zoom(value) {
        const localValue = Number(value);
        if (Number.isNaN(localValue)) {
            return;
        }
        const old = this[zoomValue];
        if (old === localValue) {
            return;
        }
        this[zoomValue] = localValue;
        this.gestures.updateScale();
        this.requestUpdate('zoom', old);
    }
    /**
     * Gets or sets the number of pixels that an element's content is scrolled horizontally.
     * Unlike regular HTML elements, this can be a negative value as it is possible to
     * scroll outside the working area.
     */
    get scrollLeft() {
        const s = this.gestures;
        return s && s.left || 0;
    }
    /**
     * @param value The x-axis position value
     */
    set scrollLeft(value) {
        this.gestures.left = value;
    }
    /**
     * Gets or sets the number of pixels that an element's content is scrolled vertically.
     * Unlike regular HTML elements, this can be a negative value as it is possible to
     * scroll outside the working area.
     */
    get scrollTop() {
        const s = this.gestures;
        return s && s.top || 0;
    }
    /**
     * @param value The y-axis position value
     */
    set scrollTop(value) {
        this.gestures.top = value;
    }
    get canvas() {
        if (!this[canvasRef]) {
            this[canvasRef] = this.shadowRoot?.querySelector('.canvas');
        }
        return this[canvasRef];
    }
    get associationSvg() {
        if (!this[svgRef]) {
            this[svgRef] = this.shadowRoot?.querySelector('.association');
        }
        return this[svgRef];
    }
    /**
     * The width of the canvas element, in pixels
     */
    get width() {
        return this[widthValue] || defaultCanvasWidth;
    }
    set width(value) {
        const old = this[widthValue];
        if (old === value) {
            return;
        }
        if (!value || Number.isNaN(value)) {
            this[widthValue] = undefined;
        }
        else {
            this[widthValue] = value;
        }
        this.requestUpdate('width', old);
    }
    /**
     * The height of the canvas element, in pixels
     */
    get height() {
        return this[heightValue] || defaultCanvasHeight;
    }
    set height(value) {
        const old = this[heightValue];
        if (old === value) {
            return;
        }
        if (!value || Number.isNaN(value)) {
            this[heightValue] = undefined;
        }
        else {
            this[heightValue] = value;
        }
        this.requestUpdate('height', old);
    }
    /**
     * When set it instruct the visualization workspace to grow over the currently set `width` and `height`
     * when a new added item is placed outside the bounds of the workspace.
     */
    get autoResize() {
        return this[autoResizeValue];
    }
    set autoResize(value) {
        const old = this[autoResizeValue];
        if (old === value) {
            return;
        }
        this[autoResizeValue] = value;
        this.requestUpdate('autoResize', old);
        if (value === true) {
            this.sizing.connect();
        }
        else if (this.sizing.connected) {
            this.sizing.disconnect();
        }
    }
    constructor() {
        super();
        this[_a] = false;
        /**
         * The current scale of the visualization
         */
        this.scale = 1;
        this.gestures = new WorkspaceGestures(this);
        this.selection = new SelectionManager(this);
        this.edges = new WorkspaceEdges(this);
        this.anchors = new AssociationAnchors(this);
        this.sizing = new WorkspaceSizing(this);
        this.addEventListener('geometrychange', this[geometryChangeHandler].bind(this));
    }
    connectedCallback() {
        super.connectedCallback();
        this.gestures.connect();
        this.selection.connect();
        this.edges.connect();
        this.anchors.connect();
    }
    disconnectedCallback() {
        super.disconnectedCallback();
        this.gestures.disconnect();
        this.selection.disconnect();
        this.edges.disconnect();
        this.anchors.disconnect();
    }
    firstUpdated(cp) {
        super.firstUpdated(cp);
        const { top, left } = this.gestures;
        if (top === null || left === null) {
            this.gestures.scrollTo(0, 0);
            // this.center();
        }
        this.edges.listenContent();
    }
    /**
     * Clears the state of the workspace.
     */
    clear() {
        this.edges.clear();
        this.selection.deselectAll();
    }
    /**
     * Centers the workspace.
     */
    center() {
        const { width: cWidth = defaultCanvasWidth, height: cHeight = defaultCanvasHeight } = this;
        const { height, width } = this.getBoundingClientRect();
        const midWidth = cWidth / 2;
        const midHeight = cHeight / 2;
        const left = midWidth - width / 2;
        const top = midHeight - height / 2;
        this.gestures.left = -left;
        this.gestures.top = -top;
    }
    [(_a = autoResizeValue, notifyZoom)]() {
        if (this[zoomTimeout]) {
            clearTimeout(this[zoomTimeout]);
        }
        this[zoomTimeout] = setTimeout(() => {
            this.dispatchEvent(new Event('zoomchange'));
        }, 1);
    }
    async [geometryChangeHandler](e) {
        const source = e.target;
        await this.edges.update(source.dataset.key);
    }
    /**
     * Scrolls the element by the given amount.
     * @param {ScrollToOptions|number} xCoordOrOptions The horizontal pixel value that you want to scroll by
     * or the scroll options. When passed value is the `ScrollToOptions` interface then
     * the second argument is ignored.
     * @param {number=} yCoord The vertical pixel value that you want to scroll by.
     */
    scrollBy(xCoordOrOptions, yCoord) {
        this.gestures.scrollBy(xCoordOrOptions, yCoord);
    }
    /**
     * Scrolls to a particular set of coordinates inside the element.
     *
     * @param xCoordOrOptions The pixel along the horizontal axis of the element
     * that you want displayed in the upper left. When passed value is the `ScrollToOptions` interface then
     * the second argument is ignored.
     * @param yCoord The pixel along the vertical axis of the element that you want displayed in the upper left.
     */
    scrollTo(xCoordOrOptions, yCoord) {
        this.gestures.scrollTo(xCoordOrOptions, yCoord);
    }
    /**
     * Scrolls the view if the position defined by `x` and `y` arguments requires
     * the view to be moved.
     *
     * @param x The x coordinate of the point
     * @param y The y coordinate of the point
     * @returns true if the canvas was moved
     */
    scrollIfNeeded(x, y) {
        return this.gestures.scrollIfNeeded(x, y);
    }
    render() {
        const { scale, scrollLeft, scrollTop } = this;
        const styles = {
            transform: `scale(${scale}) translate(${scrollLeft}px, ${scrollTop}px)`,
            width: `${this.width}px`,
            height: `${this.height}px`,
        };
        return html `
      <div
        class="content canvas"
        style="${styleMap(styles)}"
      >
        ${this.renderLinesTemplate()}
        <slot></slot>
      </div>
    `;
    }
    /**
     * @return {SVGTemplateResult} The template for the associations
     */
    renderLinesTemplate() {
        const { debug } = this;
        const { edges } = this.edges;
        const primarySelected = [];
        const secondarySelected = [];
        const hovered = [];
        const rest = [];
        edges.forEach((item) => {
            const line = ShapeArtist.line(item, debug);
            const { shape } = item;
            const { selection = {} } = shape;
            if (selection.primary) {
                primarySelected.push(line);
            }
            else if (selection.secondary) {
                secondarySelected.push(line);
            }
            else if (selection.hover) {
                hovered.push(line);
            }
            else {
                rest.push(line);
            }
        });
        const edgesResult = primarySelected.concat(secondarySelected).concat(hovered).concat(rest).reverse();
        return svg `
    <svg width="100%" height="100%" class="association">
    ${edgesResult.length ? edgesResult : ''}
    </svg>`;
    }
}
__decorate([
    property({ type: Number, reflect: true })
], VizWorkspaceElement.prototype, "zoom", null);
__decorate([
    property({ type: Number })
], VizWorkspaceElement.prototype, "scrollLeft", null);
__decorate([
    property({ type: Number })
], VizWorkspaceElement.prototype, "scrollTop", null);
__decorate([
    property({ type: Number })
], VizWorkspaceElement.prototype, "width", null);
__decorate([
    property({ type: Number })
], VizWorkspaceElement.prototype, "height", null);
__decorate([
    property({ type: Number, reflect: true })
], VizWorkspaceElement.prototype, "autoResize", null);
__decorate([
    property({ type: Boolean, reflect: true })
], VizWorkspaceElement.prototype, "debug", void 0);
__decorate([
    property({ type: Number })
], VizWorkspaceElement.prototype, "scale", void 0);
//# sourceMappingURL=VizWorkspaceElement.js.map