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;
};
var AffineDocRemoteSelectionWidget_1;
import { BlockSelection, TextSelection, } from '@blockeditor/block-std';
import { assertExists, throttle } from '@blockeditor/global/utils';
import { WidgetElement } from '@blockeditor/lit';
import {} from '@blockeditor/store';
import { css, html, nothing } from 'lit';
import { customElement } from 'lit/decorators.js';
import { styleMap } from 'lit/directives/style-map.js';
import { RemoteColorManager } from '../../../page-block/remote-color-manager/remote-color-manager.js';
import { isPageComponent } from '../../../page-block/utils/guard.js';
import { cursorStyle, filterCoveringRects, selectionStyle } from './utils.js';
export const AFFINE_DOC_REMOTE_SELECTION_WIDGET = 'affine-doc-remote-selection-widget';
let AffineDocRemoteSelectionWidget = AffineDocRemoteSelectionWidget_1 = class AffineDocRemoteSelectionWidget extends WidgetElement {
    constructor() {
        super(...arguments);
        this._remoteColorManager = null;
        this._remoteSelections = [];
        this._resizeObserver = new ResizeObserver(() => {
            this.requestUpdate();
        });
        this._abortController = new AbortController();
    }
    get _selectionManager() {
        return this.host.selection;
    }
    get _container() {
        return this.offsetParent;
    }
    get _containerRect() {
        return this.offsetParent?.getBoundingClientRect();
    }
    connectedCallback() {
        super.connectedCallback();
        if (!AffineDocRemoteSelectionWidget_1.enable)
            return;
        this.disposables.add(this._selectionManager.slots.remoteChanged.on(throttle((remoteSelections) => {
            const status = this.page.awarenessStore.getStates();
            this._remoteSelections = [...remoteSelections.entries()].map(([id, selections]) => {
                return {
                    id,
                    selections,
                    user: status.get(id)?.user,
                };
            });
            this.requestUpdate();
        }, 100)));
        this.handleEvent('wheel', () => {
            this.requestUpdate();
        });
        this.disposables.addFromEvent(window, 'resize', () => {
            this.requestUpdate();
        });
        this._remoteColorManager = new RemoteColorManager(this.host);
    }
    disconnectedCallback() {
        super.disconnectedCallback();
        this._resizeObserver.disconnect();
        this._abortController.abort();
    }
    _getSelectionRect(selections) {
        if (!isPageComponent(this.blockElement)) {
            throw new Error('remote selection widget must be used in page component');
        }
        const textSelection = selections.find(selection => selection instanceof TextSelection);
        const blockSelections = selections.filter(selection => selection instanceof BlockSelection);
        const container = this._container;
        const containerRect = this._containerRect;
        if (textSelection) {
            const rangeManager = this.host.rangeManager;
            assertExists(rangeManager);
            const range = rangeManager.textSelectionToRange(textSelection);
            if (range) {
                const nativeRects = Array.from(range.getClientRects());
                const rectsWithoutFiltered = nativeRects
                    .map(rect => ({
                    width: rect.right - rect.left,
                    height: rect.bottom - rect.top,
                    top: rect.top -
                        (containerRect?.top ?? 0) +
                        (container?.scrollTop ?? 0),
                    left: rect.left -
                        (containerRect?.left ?? 0) +
                        (container?.scrollLeft ?? 0),
                }))
                    .filter(rect => rect.width > 0 && rect.height > 0);
                return filterCoveringRects(rectsWithoutFiltered);
            }
        }
        else if (blockSelections.length > 0) {
            return blockSelections.flatMap(blockSelection => {
                const blockElement = this.host.view.viewFromPath('block', blockSelection.path);
                if (blockElement) {
                    const rect = blockElement.getBoundingClientRect();
                    return {
                        width: rect.width,
                        height: rect.height,
                        top: rect.top -
                            (containerRect?.top ?? 0) +
                            (container?.scrollTop ?? 0),
                        left: rect.left -
                            (containerRect?.left ?? 0) +
                            (container?.scrollLeft ?? 0),
                    };
                }
                return [];
            });
        }
        return [];
    }
    _getCursorRect(selections) {
        if (!isPageComponent(this.blockElement)) {
            throw new Error('remote selection widget must be used in page component');
        }
        const textSelection = selections.find(selection => selection instanceof TextSelection);
        const blockSelections = selections.filter(selection => selection instanceof BlockSelection);
        const container = this._container;
        const containerRect = this._containerRect;
        if (textSelection) {
            const rangeManager = this.host.rangeManager;
            assertExists(rangeManager);
            const range = rangeManager.pointToRange({
                path: textSelection.to
                    ? textSelection.to.path
                    : textSelection.from.path,
                index: textSelection.to
                    ? textSelection.to.index + textSelection.to.length
                    : textSelection.from.index + textSelection.from.length,
                length: 0,
            });
            if (!range) {
                return null;
            }
            const container = this._container;
            const containerRect = this._containerRect;
            const rangeRects = Array.from(range.getClientRects());
            if (rangeRects.length === 1) {
                const rect = rangeRects[0];
                return {
                    width: 2,
                    height: rect.height,
                    top: rect.top - (containerRect?.top ?? 0) + (container?.scrollTop ?? 0),
                    left: rect.left -
                        (containerRect?.left ?? 0) +
                        (container?.scrollLeft ?? 0),
                };
            }
        }
        else if (blockSelections.length > 0) {
            const lastBlockSelection = blockSelections[blockSelections.length - 1];
            const blockElement = this.host.view.viewFromPath('block', lastBlockSelection.path);
            if (blockElement) {
                const rect = blockElement.getBoundingClientRect();
                return {
                    width: 2,
                    height: rect.height,
                    top: rect.top - (containerRect?.top ?? 0) + (container?.scrollTop ?? 0),
                    left: rect.left +
                        rect.width -
                        (containerRect?.left ?? 0) +
                        (container?.scrollLeft ?? 0),
                };
            }
        }
        return null;
    }
    render() {
        if (this._remoteSelections.length === 0 ||
            !AffineDocRemoteSelectionWidget_1.enable) {
            return nothing;
        }
        const remoteUsers = new Set();
        const selections = this._remoteSelections.flatMap(({ selections, id, user }) => {
            if (remoteUsers.has(id)) {
                return [];
            }
            else {
                remoteUsers.add(id);
            }
            return {
                id,
                selections,
                rects: this._getSelectionRect(selections),
                user,
            };
        });
        const remoteColorManager = this._remoteColorManager;
        assertExists(remoteColorManager);
        return html `<div>
      ${selections.flatMap(selection => {
            const color = remoteColorManager.get(selection.id);
            if (!color)
                return;
            const cursorRect = this._getCursorRect(selection.selections);
            return selection.rects
                .map(r => html `<div style="${selectionStyle(r, color)}"></div>`)
                .concat([
                html `
              <div
                style="${cursorRect
                    ? cursorStyle(cursorRect, color)
                    : styleMap({
                        display: 'none',
                    })}"
              >
                <div
                  style="${styleMap({
                    position: 'relative',
                    height: '100%',
                })}"
                >
                  <div
                    style="${styleMap({
                    position: 'absolute',
                    left: '-4px',
                    bottom: `${cursorRect?.height ? cursorRect.height - 4 : 0}px`,
                    backgroundColor: color,
                    color: 'white',
                    maxWidth: '160px',
                    padding: '0 3px',
                    border: '1px solid var(--affine-pure-black-20)',
                    boxShadow: '0px 1px 6px 0px rgba(0, 0, 0, 0.16)',
                    borderRadius: '4px',
                    fontSize: '12px',
                    lineHeight: '18px',
                    overflow: 'hidden',
                    textOverflow: 'ellipsis',
                    whiteSpace: 'nowrap',
                })}"
                  >
                    ${selection.user?.name ?? 'Unknown'}
                  </div>
                </div>
              </div>
            `,
            ]);
        })}
    </div>`;
    }
};
// avoid being unable to select text by mouse click or drag
AffineDocRemoteSelectionWidget.styles = css `
    :host {
      pointer-events: none;
    }
  `;
AffineDocRemoteSelectionWidget.enable = true;
AffineDocRemoteSelectionWidget = AffineDocRemoteSelectionWidget_1 = __decorate([
    customElement(AFFINE_DOC_REMOTE_SELECTION_WIDGET)
], AffineDocRemoteSelectionWidget);
export { AffineDocRemoteSelectionWidget };
//# sourceMappingURL=doc-remote-selection.js.map