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 { assertExists, noop } from '@blockeditor/global/utils';
import { WithDisposable } from '@blockeditor/lit';
import { css, html, LitElement, nothing } from 'lit';
import { customElement, property, query, state } from 'lit/decorators.js';
import { EDGELESS_BLOCK_CHILD_PADDING } from '../../../../_common/consts.js';
import { requestConnectedFrame } from '../../../../_common/utils/event.js';
import { buildPath, getModelByBlockComponent, getRectByBlockElement, Point, } from '../../../../_common/utils/index.js';
import { almostEqual } from '../../../../_common/utils/math.js';
import { deserializeXYWH, serializeXYWH, } from '../../../../surface-block/index.js';
import { DefaultModeDragType, } from '../../controllers/tools/default-tool.js';
import { DEFAULT_NOTE_HEIGHT } from '../../utils/consts.js';
import { isNoteBlock } from '../../utils/query.js';
import { NoteSlicerButton } from './slicer-button.js';
import { NoteSlicerIndicator } from './slicer-indicator.js';
import { findClosestBlock } from './utils.js';
noop(NoteSlicerButton);
noop(NoteSlicerIndicator);
let NoteSlicer = class NoteSlicer extends WithDisposable(LitElement) {
    constructor() {
        super(...arguments);
        this._lastPosition = null;
        this._noteModel = null;
        this._blockModel = null;
        this._lastPointerState = null;
    }
    connectedCallback() {
        super.connectedCallback();
        if (!this.edgelessPage.service)
            return;
        this._disposables.add(this.edgelessPage.service.uiEventDispatcher.add('pointerMove', ctx => {
            const e = ctx.get('pointerState');
            this._lastPointerState = e;
            this._updateVisibility(this._lastPointerState);
        }));
        this._disposables.add(this.edgelessPage.service.uiEventDispatcher.add('wheel', () => {
            this._hide();
        }));
        this._disposables.add(this.edgelessPage.page.slots.blockUpdated.on(() => {
            if (this._lastPointerState) {
                this._updateVisibility(this._lastPointerState);
            }
        }));
        this._disposables.add(this.edgelessPage.selectionManager.slots.updated.on(() => {
            if (this._lastPointerState) {
                this._updateVisibility(this._lastPointerState);
            }
        }));
    }
    get selection() {
        return this.edgelessPage.selectionManager;
    }
    get _notHovering() {
        return (this.edgelessPage.edgelessTool.type !== 'default' ||
            this.edgelessPage.tools.currentController
                .dragType !== DefaultModeDragType.None);
    }
    get _zoom() {
        return this.edgelessPage?.surface?.viewport.zoom ?? 1;
    }
    get editorHost() {
        return this.edgelessPage.host;
    }
    _updateVisibility(e) {
        const block = this.selection.elements[0];
        if (this._zoom < 0.4 || this._notHovering || !isNoteBlock(block)) {
            this._hide();
            return;
        }
        if (isNoteBlock(block)) {
            const editingState = this._getEditingState(e, block);
            if (editingState) {
                this._show(e, editingState);
            }
            else {
                this._hide();
            }
        }
        else {
            this._hide();
        }
    }
    _getEditingState(e, block) {
        const noteBlockElement = this.editorHost.view.viewFromPath('block', buildPath(block));
        if (!noteBlockElement)
            return null;
        const { raw: { clientX, clientY }, } = e;
        const element = findClosestBlock(noteBlockElement, new Point(clientX, clientY));
        if (!element)
            return null;
        const elementRect = getRectByBlockElement(element);
        const onUpperPart = clientY <= elementRect.y + elementRect.height / 2;
        const nearbyBlockElement = onUpperPart
            ? element.previousElementSibling
            : element.nextElementSibling;
        if (!nearbyBlockElement) {
            return null;
        }
        const currentBlock = getModelByBlockComponent(element);
        const nearbyBlock = getModelByBlockComponent(nearbyBlockElement);
        const nearbyBlockRect = nearbyBlockElement.getBoundingClientRect();
        const upperBlockRect = onUpperPart ? nearbyBlockRect : elementRect;
        const lowerBlockRect = onUpperPart ? elementRect : nearbyBlockRect;
        return {
            note: block,
            noteElement: noteBlockElement,
            upperBlock: onUpperPart ? nearbyBlock : currentBlock,
            upperBlockElement: (onUpperPart
                ? nearbyBlockElement
                : element),
            gapRect: new DOMRect(upperBlockRect.x, upperBlockRect.y + upperBlockRect.height, upperBlockRect.width, lowerBlockRect.y - (upperBlockRect.y + upperBlockRect.height)),
        };
    }
    _show(_event, modelState) {
        const { note, noteElement, upperBlock, upperBlockElement, gapRect } = modelState;
        if (!noteElement.parentElement) {
            this._hide();
            return;
        }
        const edgelessRect = this.edgelessPage.getBoundingClientRect();
        const shouldTransition = note === this._noteModel;
        const noteContainer = noteElement.closest('.edgeless-block-portal-note');
        assertExists(noteContainer);
        const [baseX, baseY, noteWidth] = deserializeXYWH(note.xywh);
        const transformX = baseX;
        const transformY = this.edgelessPage.surface.toModelCoord(gapRect.x - edgelessRect.x, gapRect.y - edgelessRect.y + gapRect.height / 2)[1];
        const sliceVerticalPos = baseY + upperBlockElement.offsetHeight + upperBlockElement.offsetTop;
        if (this._lastPosition) {
            if (!almostEqual(transformX, this._lastPosition.transformX) ||
                !almostEqual(transformY, this._lastPosition.transformY)) {
                if (this.style.zIndex)
                    this.style.removeProperty('z-index');
                this._slicerButton?.reset();
                this._indicatorLine?.reset();
            }
            else {
                return;
            }
        }
        this._noteModel = note;
        this._blockModel = upperBlock;
        this._lastPosition = {
            transformX,
            transformY,
            width: noteWidth - EDGELESS_BLOCK_CHILD_PADDING * 2,
            gapRect,
            sliceVerticalPos,
        };
        requestConnectedFrame(() => {
            if (this.style.display === 'block' && shouldTransition) {
                this.style.transition = 'transform .2s ease-in-out';
            }
            else {
                this.style.display = 'block';
                this.style.removeProperty('transition');
            }
            this.style.transform = `translate3d(${transformX}px, ${transformY}px, 0) translate3d(0, -50%, 0) scale(${1 / this._zoom})`;
            this.style.zIndex = noteContainer.style.zIndex;
        }, this);
    }
    _hide() {
        this.style.removeProperty('z-index');
        this.style.removeProperty('display');
        this._slicerButton?.reset();
        this._indicatorLine?.reset();
        this._lastPosition = null;
        this._blockModel = null;
        this._noteModel = null;
        this._lastPointerState = null;
    }
    _increaseZIndex() {
        this.style.zIndex = (Number(this.style.zIndex) + 1).toString();
    }
    _showIndicator() {
        if (this._lastPosition) {
            this._indicatorLine.show();
        }
    }
    _sliceNote() {
        if (!this._blockModel || !this._noteModel || !this._lastPosition)
            return;
        const page = this.edgelessPage.page;
        const { index: originIndex, xywh, background, children } = this._noteModel;
        const sliceIndex = children.findIndex(block => block.id === this._blockModel?.id);
        const resetBlocks = children.slice(sliceIndex + 1);
        const { sliceVerticalPos } = this._lastPosition;
        const [x, , width] = deserializeXYWH(xywh);
        const newNoteId = this.edgelessPage.surface.addElement('affine:note', {
            background,
            xywh: serializeXYWH(x, sliceVerticalPos + EDGELESS_BLOCK_CHILD_PADDING + 30, width, DEFAULT_NOTE_HEIGHT),
            index: originIndex + 1,
        }, page.root?.id);
        page.moveBlocks(resetBlocks, page.getBlockById(newNoteId));
        this._hide();
    }
    render() {
        if (!this._lastPosition)
            return nothing;
        return html `<div class="affine-note-slicer-container">
      <note-slicer-button
        .zoom=${this._zoom}
        @showindicator=${this._showIndicator}
        @slice=${this._sliceNote}
        @increasezindex=${this._increaseZIndex}
      ></note-slicer-button>
      <note-slicer-indicator
        .zoom=${this._zoom}
        .offset=${EDGELESS_BLOCK_CHILD_PADDING}
        .width=${this._lastPosition?.width ?? 0}
      ></note-slicer-indicator>
    </div> `;
    }
};
NoteSlicer.styles = css `
    :host {
      display: none;
      position: absolute;
      top: 0;
      left: 0;
      transform-origin: left center;
    }

    .affine-note-slicer-container {
      display: flex;
      justify-content: flex-start;
      align-items: center;
    }
  `;
__decorate([
    property({ attribute: false })
], NoteSlicer.prototype, "edgelessPage", void 0);
__decorate([
    query('note-slicer-button')
], NoteSlicer.prototype, "_slicerButton", void 0);
__decorate([
    query('note-slicer-indicator')
], NoteSlicer.prototype, "_indicatorLine", void 0);
__decorate([
    state()
], NoteSlicer.prototype, "_lastPosition", void 0);
NoteSlicer = __decorate([
    customElement('affine-note-slicer')
], NoteSlicer);
export { NoteSlicer };
//# sourceMappingURL=index.js.map