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 { WithDisposable } from '@blockeditor/lit';
import { css, html, LitElement, nothing } from 'lit';
import { customElement, property, query, queryAll } from 'lit/decorators.js';
import { LineWidth } from '../../../../_common/types.js';
export class LineWidthEvent extends Event {
    constructor(type, { detail, composed, bubbles, }) {
        super(type, { bubbles, composed });
        this.detail = detail;
    }
}
let EdgelessLineWidthPanel = class EdgelessLineWidthPanel extends WithDisposable(LitElement) {
    constructor() {
        super(...arguments);
        this.selectedSize = LineWidth.LINE_WIDTH_TWO;
        this.hasTooltip = true;
        this.disable = false;
        this._dragConfig = null;
        this._updateIconsColor = () => {
            if (!this._dragHandle.offsetParent) {
                requestAnimationFrame(() => this._updateIconsColor());
                return;
            }
            const dragHandleRect = this._dragHandle.getBoundingClientRect();
            const dragHandleCenterX = dragHandleRect.left + dragHandleRect.width / 2;
            const icons = Array.from(this._lineWidthIcons);
            // All the icons located at the left of the drag handle should be filled with the icon color.
            const leftIcons = icons.filter(icon => {
                const iconRect = icon.getBoundingClientRect();
                const iconCenterX = iconRect.left + iconRect.width / 2;
                return iconCenterX < dragHandleCenterX;
            });
            // All the icons located at the right of the drag handle should be filled with the border color.
            const rightIcons = icons.filter(icon => {
                const iconRect = icon.getBoundingClientRect();
                const iconCenterX = iconRect.left + iconRect.width / 2;
                return iconCenterX > dragHandleCenterX;
            });
            leftIcons.forEach(icon => (icon.style.backgroundColor = 'var(--affine-icon-color)'));
            rightIcons.forEach(icon => (icon.style.backgroundColor = 'var(--affine-border-color)'));
        };
        this._getDragHandlePosition = (e, config) => {
            const x = e.clientX;
            const { boundLeft, bottomLineWidth, stepWidth, containerWidth } = config;
            let steps;
            if (x <= boundLeft) {
                steps = 0;
            }
            else if (x - boundLeft >= containerWidth) {
                steps = 100;
            }
            else {
                steps = Math.floor((x - boundLeft) / stepWidth);
            }
            // The drag handle should not be dragged to the left of the first icon or right of the last icon.
            // Calculate the drag handle position based on the steps.
            const bottomLineOffsetX = 4;
            const bottomLineStepWidth = (bottomLineWidth - bottomLineOffsetX) / 100;
            const dragHandlerPosition = steps * bottomLineStepWidth;
            return dragHandlerPosition;
        };
        this._onPointerDown = (e) => {
            e.preventDefault();
            if (this.disable)
                return;
            const { left, width } = this._lineWidthPanel.getBoundingClientRect();
            const bottomLineWidth = this._bottomLine.getBoundingClientRect().width;
            this._dragConfig = {
                stepWidth: width / 100,
                boundLeft: left,
                containerWidth: width,
                bottomLineWidth,
            };
            this._onPointerMove(e);
        };
        this._onPointerMove = (e) => {
            e.preventDefault();
            if (!this._dragConfig)
                return;
            const dragHandlerPosition = this._getDragHandlePosition(e, this._dragConfig);
            this._dragHandle.style.left = `${dragHandlerPosition}%`;
            this._lineWidthOverlay.style.width = `${dragHandlerPosition}%`;
            this._updateIconsColor();
        };
        this._onPointerUp = (e) => {
            e.preventDefault();
            if (!this._dragConfig)
                return;
            const dragHandlerPosition = this._getDragHandlePosition(e, this._dragConfig);
            this._updateLineWidthPanelByDragHandlePosition(dragHandlerPosition);
            this._dragConfig = null;
        };
        this._onPointerOut = (e) => {
            // If the pointer is out of the line width panel
            // Stop dragging and update the selected size by nearest size.
            e.preventDefault();
            if (!this._dragConfig)
                return;
            const dragHandlerPosition = this._getDragHandlePosition(e, this._dragConfig);
            this._updateLineWidthPanelByDragHandlePosition(dragHandlerPosition);
            this._dragConfig = null;
        };
    }
    _updateLineWidthPanel(selectedSize) {
        if (!this._lineWidthOverlay)
            return;
        let width = 0;
        let dragHandleOffsetX = 0;
        switch (selectedSize) {
            case LineWidth.LINE_WIDTH_TWO:
                width = 0;
                break;
            case LineWidth.LINE_WIDTH_FOUR:
                width = 16;
                dragHandleOffsetX = 1;
                break;
            case LineWidth.LINE_WIDTH_SIX:
                width = 32;
                dragHandleOffsetX = 2;
                break;
            case LineWidth.LINE_WIDTH_EIGHT:
                width = 48;
                dragHandleOffsetX = 3;
                break;
            case LineWidth.LINE_WIDTH_TEN:
                width = 64;
                dragHandleOffsetX = 4;
                break;
            default:
                width = 80;
                dragHandleOffsetX = 4;
        }
        dragHandleOffsetX += 4;
        this._lineWidthOverlay.style.width = `${width}%`;
        this._dragHandle.style.left = `${width}%`;
        this._dragHandle.style.transform = `translateY(-50%) translateX(${dragHandleOffsetX}px)`;
        this._updateIconsColor();
    }
    _updateLineWidthPanelByDragHandlePosition(dragHandlerPosition) {
        // Calculate the selected size based on the drag handle position.
        // Need to select the nearest size.
        let selectedSize = this.selectedSize;
        if (dragHandlerPosition <= 12) {
            selectedSize = LineWidth.LINE_WIDTH_TWO;
        }
        else if (dragHandlerPosition > 12 && dragHandlerPosition <= 26) {
            selectedSize = LineWidth.LINE_WIDTH_FOUR;
        }
        else if (dragHandlerPosition > 26 && dragHandlerPosition <= 40) {
            selectedSize = LineWidth.LINE_WIDTH_SIX;
        }
        else if (dragHandlerPosition > 40 && dragHandlerPosition <= 54) {
            selectedSize = LineWidth.LINE_WIDTH_EIGHT;
        }
        else if (dragHandlerPosition > 54 && dragHandlerPosition <= 68) {
            selectedSize = LineWidth.LINE_WIDTH_TEN;
        }
        else {
            selectedSize = LineWidth.LINE_WIDTH_TWELVE;
        }
        this._updateLineWidthPanel(selectedSize);
        this._onSelect(selectedSize);
    }
    _onSelect(lineWidth) {
        // If the selected size is the same as the previous one, do nothing.
        if (lineWidth === this.selectedSize)
            return;
        this.dispatchEvent(new LineWidthEvent('select', {
            detail: lineWidth,
            composed: true,
            bubbles: true,
        }));
        this.selectedSize = lineWidth;
    }
    firstUpdated() {
        this._updateLineWidthPanel(this.selectedSize);
        this._disposables.addFromEvent(this, 'pointerdown', this._onPointerDown);
        this._disposables.addFromEvent(this, 'pointermove', this._onPointerMove);
        this._disposables.addFromEvent(this, 'pointerup', this._onPointerUp);
        this._disposables.addFromEvent(this, 'pointerout', this._onPointerOut);
    }
    disconnectedCallback() {
        this._disposables.dispose();
    }
    render() {
        return html ` <style>
        .line-width-panel {
          opacity: ${this.disable ? '0.5' : '1'};
        }
      </style>
      <div
        class="line-width-panel"
        @mousedown="${(e) => e.preventDefault()}"
      >
        <div class="line-width-button">
          <div class="line-width-icon"></div>
        </div>
        <div class="line-width-button">
          <div class="line-width-icon"></div>
        </div>
        <div class="line-width-button">
          <div class="line-width-icon"></div>
        </div>
        <div class="line-width-button">
          <div class="line-width-icon"></div>
        </div>
        <div class="line-width-button">
          <div class="line-width-icon"></div>
        </div>
        <div class="line-width-button">
          <div class="line-width-icon"></div>
        </div>
        <div class="drag-handle"></div>
        <div class="bottom-line"></div>
        <div class="line-width-overlay"></div>
        ${this.hasTooltip
            ? html `<affine-tooltip>Thickness</affine-tooltip>`
            : nothing}
      </div>`;
    }
};
EdgelessLineWidthPanel.styles = css `
    :host {
      display: flex;
      box-sizing: border-box;
      background: var(--affine-background-overlay-panel-color);
    }

    .line-width-panel {
      display: flex;
      flex-direction: row-reverse;
      align-items: center;
      justify-content: space-between;
      position: relative;
      width: 108px;
      margin: 4px 0;
      cursor: default;
    }

    .line-width-button {
      display: flex;
      align-items: center;
      justify-content: center;
      width: 16px;
      height: 16px;
      z-index: 2;
    }

    .line-width-icon {
      width: 4px;
      height: 4px;
      border-radius: 50%;
      background-color: var(--affine-border-color);
    }

    .line-width-button:nth-child(1) {
      margin-right: 0;
    }

    .line-width-button:nth-child(6) {
      margin-left: 0;
    }

    .drag-handle {
      position: absolute;
      left: 0;
      top: 50%;
      width: 8px;
      height: 8px;
      transform: translateY(-50%) translateX(4px);
      border-radius: 50%;
      background-color: var(--affine-icon-color);
      z-index: 3;
    }

    .bottom-line,
    .line-width-overlay {
      left: 8px;
      top: 50%;
      transform: translateY(-50%);
      height: 1px;
      background-color: var(--affine-border-color);
      position: absolute;
    }

    .bottom-line {
      width: calc(100% - 16px);
      background-color: var(--affine-border-color);
    }

    .line-width-overlay {
      width: 0;
      background-color: var(--affine-icon-color);
      z-index: 1;
    }
  `;
__decorate([
    property({ attribute: false })
], EdgelessLineWidthPanel.prototype, "selectedSize", void 0);
__decorate([
    property({ attribute: false })
], EdgelessLineWidthPanel.prototype, "hasTooltip", void 0);
__decorate([
    property({ attribute: false })
], EdgelessLineWidthPanel.prototype, "disable", void 0);
__decorate([
    query('.line-width-panel')
], EdgelessLineWidthPanel.prototype, "_lineWidthPanel", void 0);
__decorate([
    query('.line-width-overlay')
], EdgelessLineWidthPanel.prototype, "_lineWidthOverlay", void 0);
__decorate([
    queryAll('.line-width-icon')
], EdgelessLineWidthPanel.prototype, "_lineWidthIcons", void 0);
__decorate([
    query('.bottom-line')
], EdgelessLineWidthPanel.prototype, "_bottomLine", void 0);
__decorate([
    query('.drag-handle')
], EdgelessLineWidthPanel.prototype, "_dragHandle", void 0);
EdgelessLineWidthPanel = __decorate([
    customElement('edgeless-line-width-panel')
], EdgelessLineWidthPanel);
export { EdgelessLineWidthPanel };
//# sourceMappingURL=line-width-panel.js.map