var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
    return c > 3 && r && Object.defineProperty(target, key, r), r;
};
import '../buttons/menu-button.js';
import '../../../../_common/components/menu-divider.js';
import { WithDisposable } from '@blockeditor/lit';
import { html, LitElement } from 'lit';
import { customElement, property } from 'lit/decorators.js';
import { styleMap } from 'lit/directives/style-map.js';
import { AlignBottomIcon, AlignDistributeHorizontallyIcon, AlignDistributeVerticallyIcon, AlignHorizontallyIcon, AlignLeftIcon, AlignRightIcon, AlignTopIcon, AlignVerticallyIcon, SmallArrowDownIcon, } from '../../../../_common/icons/index.js';
import { Bound, ConnectorElement, GroupElement, } from '../../../../surface-block/index.js';
let EdgelessAlignButton = class EdgelessAlignButton extends WithDisposable(LitElement) {
    get elements() {
        return this.edgeless.selectionManager.elements;
    }
    firstUpdated() {
        this._disposables.add(this.edgeless.selectionManager.slots.updated.on(() => this.requestUpdate()));
    }
    _updateXYWH(ele, bound) {
        if (ele instanceof ConnectorElement) {
            this.edgeless.surface.connector.updateXYWH(ele, bound);
        }
        else if (ele instanceof GroupElement) {
            const groupBound = Bound.deserialize(ele.xywh);
            ele.childElements.forEach(child => {
                const newBound = Bound.deserialize(child.xywh);
                newBound.x += bound.x - groupBound.x;
                newBound.y += bound.y - groupBound.y;
                this._updateXYWH(child, newBound);
            });
        }
        else {
            this.edgeless.surface.updateElement(ele.id, {
                xywh: bound.serialize(),
            });
        }
    }
    _alignLeft() {
        const { elements } = this;
        const bounds = elements.map(a => a.elementBound);
        const left = Math.min(...bounds.map(b => b.minX));
        elements.forEach((ele, index) => {
            const elementBound = bounds[index];
            const bound = Bound.deserialize(ele.xywh);
            const offset = bound.minX - elementBound.minX;
            bound.x = left + offset;
            this._updateXYWH(ele, bound);
        });
    }
    _alignRight() {
        const { elements } = this;
        const bounds = elements.map(a => a.elementBound);
        const right = Math.max(...bounds.map(b => b.maxX));
        elements.forEach((ele, index) => {
            const elementBound = bounds[index];
            const bound = Bound.deserialize(ele.xywh);
            const offset = bound.maxX - elementBound.maxX;
            bound.x = right - bound.w + offset;
            this._updateXYWH(ele, bound);
        });
    }
    _alignHorizontally() {
        const { elements } = this;
        const bounds = elements.map(a => a.elementBound);
        const left = Math.min(...bounds.map(b => b.minX));
        const right = Math.max(...bounds.map(b => b.maxX));
        const centerX = (left + right) / 2;
        elements.forEach(ele => {
            const bound = Bound.deserialize(ele.xywh);
            bound.x = centerX - bound.w / 2;
            this._updateXYWH(ele, bound);
        });
    }
    _alignDistributeHorizontally() {
        const { elements } = this;
        elements.sort((a, b) => a.elementBound.minX - b.elementBound.minX);
        const bounds = elements.map(a => a.elementBound);
        const left = bounds[0].minX;
        const right = bounds[bounds.length - 1].maxX;
        const totalWidth = right - left;
        const totalGap = totalWidth - elements.reduce((prev, ele) => prev + ele.elementBound.w, 0);
        const gap = totalGap / (elements.length - 1);
        let next = bounds[0].maxX + gap;
        for (let i = 1; i < elements.length - 1; i++) {
            const bound = Bound.deserialize(elements[i].xywh);
            bound.x = next + bounds[i].w / 2 - bound.w / 2;
            next += gap + bounds[i].w;
            this._updateXYWH(elements[i], bound);
        }
    }
    _alignTop() {
        const { elements } = this;
        const bounds = elements.map(a => a.elementBound);
        const top = Math.min(...bounds.map(b => b.minY));
        elements.forEach((ele, index) => {
            const elementBound = bounds[index];
            const bound = Bound.deserialize(ele.xywh);
            const offset = bound.minY - elementBound.minY;
            bound.y = top + offset;
            this._updateXYWH(ele, bound);
        });
    }
    _alignBottom() {
        const { elements } = this;
        const bounds = elements.map(a => a.elementBound);
        const bottom = Math.max(...bounds.map(b => b.maxY));
        elements.forEach((ele, index) => {
            const elementBound = bounds[index];
            const bound = Bound.deserialize(ele.xywh);
            const offset = bound.maxY - elementBound.maxY;
            bound.y = bottom - bound.h + offset;
            this._updateXYWH(ele, bound);
        });
    }
    _alignVertically() {
        const { elements } = this;
        const bounds = elements.map(a => a.elementBound);
        const top = Math.min(...bounds.map(b => b.minY));
        const bottom = Math.max(...bounds.map(b => b.maxY));
        const centerY = (top + bottom) / 2;
        elements.forEach(ele => {
            const bound = Bound.deserialize(ele.xywh);
            bound.y = centerY - bound.h / 2;
            this._updateXYWH(ele, bound);
        });
    }
    _alignDistributeVertically() {
        const { elements } = this;
        elements.sort((a, b) => a.elementBound.minY - b.elementBound.minY);
        const bounds = elements.map(a => a.elementBound);
        const top = bounds[0].minY;
        const bottom = bounds[bounds.length - 1].maxY;
        const totalHeight = bottom - top;
        const totalGap = totalHeight -
            elements.reduce((prev, ele) => prev + ele.elementBound.h, 0);
        const gap = totalGap / (elements.length - 1);
        let next = bounds[0].maxY + gap;
        for (let i = 1; i < elements.length - 1; i++) {
            const bound = Bound.deserialize(elements[i].xywh);
            bound.y = next + bounds[i].h / 2 - bound.h / 2;
            next += gap + bounds[i].h;
            this._updateXYWH(elements[i], bound);
        }
    }
    render() {
        return html `
      <edgeless-menu-button
        .iconInfo=${{
            icon: html `${AlignLeftIcon}${SmallArrowDownIcon}`,
            tooltip: 'Align Objects',
        }}
        .menuChildren=${html `<edgeless-tool-icon-button
            @click=${() => this._alignLeft()}
            .tooltip=${'Align left'}
            >${AlignLeftIcon}</edgeless-tool-icon-button
          >
          <edgeless-tool-icon-button
            @click=${() => this._alignHorizontally()}
            .tooltip=${'Align horizontally'}
          >
            ${AlignHorizontallyIcon}
          </edgeless-tool-icon-button>

          <edgeless-tool-icon-button
            @click=${() => this._alignRight()}
            .tooltip=${'Align right'}
          >
            ${AlignRightIcon}
          </edgeless-tool-icon-button>
          <edgeless-tool-icon-button
            .disabled=${this.elements.length < 3}
            @click=${() => this._alignDistributeHorizontally()}
            .tooltip=${'Distribute horizontally'}
            }
          >
            ${AlignDistributeHorizontallyIcon}
          </edgeless-tool-icon-button>
          <menu-divider
            style=${styleMap({ height: '24px' })}
            .vertical=${true}
          ></menu-divider>

          <edgeless-tool-icon-button
            @click=${() => this._alignTop()}
            .tooltip=${'Align top'}
            >${AlignTopIcon}</edgeless-tool-icon-button
          >
          <edgeless-tool-icon-button
            @click=${() => this._alignVertically()}
            .tooltip=${'Align vertically'}
          >
            ${AlignVerticallyIcon}
          </edgeless-tool-icon-button>

          <edgeless-tool-icon-button
            @click=${() => this._alignBottom()}
            .tooltip=${'Align bottom'}
          >
            ${AlignBottomIcon}
          </edgeless-tool-icon-button>
          <edgeless-tool-icon-button
            .tooltip=${'Distribute vertically'}
            .disabled=${this.elements.length < 3}
            @click=${() => this._alignDistributeVertically()}
          >
            ${AlignDistributeVerticallyIcon}
          </edgeless-tool-icon-button> `}
      >
      </edgeless-menu-button>
    `;
    }
};
__decorate([
    property({ attribute: false })
], EdgelessAlignButton.prototype, "edgeless", void 0);
EdgelessAlignButton = __decorate([
    customElement('edgeless-align-button')
], EdgelessAlignButton);
export { EdgelessAlignButton };
//# sourceMappingURL=align-button.js.map