import { __esDecorate, __runInitializers } from "tslib";
import { LitElement, html, nothing } from 'lit';
import { customElement, property, state } from 'lit/decorators.js';
import styles from './help_panel.styles.js';
import mdStyles from '../elements/highlight/MarkdownStyles.js';
import '../md/icons/ui-icon.js';
import '../md/icon-button/ui-icon-button.js';
import '../elements/highlight/marked-highlight.js';
/**
 * A panel that displays help content for a specific topic.
 * This component is used by the HelpCoordinator to show help information.
 * Uses the popover API to ensure it appears in the top layer.
 * @fires close - Dispatched when the panel is closed.
 */
let HelpPanel = (() => {
    let _classDecorators = [customElement('help-panel')];
    let _classDescriptor;
    let _classExtraInitializers = [];
    let _classThis;
    let _classSuper = LitElement;
    let _topic_decorators;
    let _topic_initializers = [];
    let _topic_extraInitializers = [];
    let _trigger_decorators;
    let _trigger_initializers = [];
    let _trigger_extraInitializers = [];
    let _opened_decorators;
    let _opened_initializers = [];
    let _opened_extraInitializers = [];
    let _isDragging_decorators;
    let _isDragging_initializers = [];
    let _isDragging_extraInitializers = [];
    let _position_decorators;
    let _position_initializers = [];
    let _position_extraInitializers = [];
    var HelpPanel = class extends _classSuper {
        static { _classThis = this; }
        static {
            const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
            _topic_decorators = [property({ type: Object })];
            _trigger_decorators = [property({ type: Object })];
            _opened_decorators = [property({ type: Boolean, reflect: true })];
            _isDragging_decorators = [state()];
            _position_decorators = [state()];
            __esDecorate(this, null, _topic_decorators, { kind: "accessor", name: "topic", static: false, private: false, access: { has: obj => "topic" in obj, get: obj => obj.topic, set: (obj, value) => { obj.topic = value; } }, metadata: _metadata }, _topic_initializers, _topic_extraInitializers);
            __esDecorate(this, null, _trigger_decorators, { kind: "accessor", name: "trigger", static: false, private: false, access: { has: obj => "trigger" in obj, get: obj => obj.trigger, set: (obj, value) => { obj.trigger = value; } }, metadata: _metadata }, _trigger_initializers, _trigger_extraInitializers);
            __esDecorate(this, null, _opened_decorators, { kind: "accessor", name: "opened", static: false, private: false, access: { has: obj => "opened" in obj, get: obj => obj.opened, set: (obj, value) => { obj.opened = value; } }, metadata: _metadata }, _opened_initializers, _opened_extraInitializers);
            __esDecorate(this, null, _isDragging_decorators, { kind: "accessor", name: "isDragging", static: false, private: false, access: { has: obj => "isDragging" in obj, get: obj => obj.isDragging, set: (obj, value) => { obj.isDragging = value; } }, metadata: _metadata }, _isDragging_initializers, _isDragging_extraInitializers);
            __esDecorate(this, null, _position_decorators, { kind: "accessor", name: "position", static: false, private: false, access: { has: obj => "position" in obj, get: obj => obj.position, set: (obj, value) => { obj.position = value; } }, metadata: _metadata }, _position_initializers, _position_extraInitializers);
            __esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
            HelpPanel = _classThis = _classDescriptor.value;
            if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
        }
        static styles = [styles, mdStyles];
        #topic_accessor_storage = __runInitializers(this, _topic_initializers, void 0);
        /**
         * The help topic to display in the panel.
         * This should be set by the HelpCoordinator when a help request is made.
         */
        get topic() { return this.#topic_accessor_storage; }
        set topic(value) { this.#topic_accessor_storage = value; }
        #trigger_accessor_storage = (__runInitializers(this, _topic_extraInitializers), __runInitializers(this, _trigger_initializers, void 0));
        /**
         * The element that triggered the help request.
         * This is used to position the help panel relative to the triggering element.
         * Might not always be set, depending on how the help request is triggered.
         */
        get trigger() { return this.#trigger_accessor_storage; }
        set trigger(value) { this.#trigger_accessor_storage = value; }
        #opened_accessor_storage = (__runInitializers(this, _trigger_extraInitializers), __runInitializers(this, _opened_initializers, false));
        /**
         * Whether the panel is currently opened.
         * This is controlled by the HelpCoordinator and reflects the current state of the panel.
         */
        get opened() { return this.#opened_accessor_storage; }
        set opened(value) { this.#opened_accessor_storage = value; }
        #isDragging_accessor_storage = (__runInitializers(this, _opened_extraInitializers), __runInitializers(this, _isDragging_initializers, false));
        get isDragging() { return this.#isDragging_accessor_storage; }
        set isDragging(value) { this.#isDragging_accessor_storage = value; }
        #position_accessor_storage = (__runInitializers(this, _isDragging_extraInitializers), __runInitializers(this, _position_initializers, { x: 20, y: 20 }));
        get position() { return this.#position_accessor_storage; }
        set position(value) { this.#position_accessor_storage = value; }
        dragOffset = (__runInitializers(this, _position_extraInitializers), { x: 0, y: 0 });
        /**
         * Duration of the opening/closing animation in ms.
         * This is defined in the css file.
         */
        animationDuration = 200;
        constructor() {
            super();
            this.popover = 'manual';
        }
        updated(cp) {
            if (cp.has('opened')) {
                if (this.opened) {
                    // @ts-expect-error This is a relatively new API, ensure your TypeScript version supports it
                    this.showPopover({ source: this.trigger });
                }
                else {
                    this.hidePopover();
                }
            }
        }
        /**
         * Handles the popover toggle event
         */
        handlePopoverToggle = (event) => {
            const toggleEvent = event;
            this.opened = toggleEvent.newState === 'open';
        };
        resetPositionAfterAnimation() {
            setTimeout(() => {
                this.style.left = 'auto';
                this.style.top = '20px';
                this.style.right = '20px';
                this.position = { x: 20, y: 20 };
            }, this.animationDuration + 1); // Add 1ms to ensure it runs after the transition
        }
        renderMarkdown(md) {
            if (!md) {
                return nothing;
            }
            return html `<marked-highlight .markdown="${md}"><div slot="markdown-html"></div></marked-highlight>`;
        }
        /**
         * Handles the close event for the help panel.
         * Dispatches a custom 'close' event and sets the opened state to false.
         * The event informs the help coordinator or any parent component that the panel has been closed.
         */
        handleClose() {
            this.dispatchEvent(new CustomEvent('close'));
            this.opened = false;
        }
        /**
         * Handles the start of a drag operation.
         * Only initiates drag if not clicking on interactive elements or text content.
         */
        handleMouseDown(event) {
            // Don't drag if clicking on interactive elements
            const target = event.target;
            if (target.closest('ui-icon-button, a, button, input, textarea, [contenteditable]')) {
                return;
            }
            // Only drag when clicking on header padding or non-text areas
            const clickedOnHeader = target.closest('.header');
            const clickedOnPadding = target.matches('.content-wrapper, .content') && this.isClickOnPadding(event, target);
            if (!clickedOnHeader && !clickedOnPadding) {
                return;
            }
            this.isDragging = true;
            const rect = this.getBoundingClientRect();
            this.dragOffset = {
                x: event.clientX - rect.left,
                y: event.clientY - rect.top,
            };
            // Prevent text selection during drag
            event.preventDefault();
            // Add global event listeners
            document.addEventListener('mousemove', this.handleMouseMove);
            document.addEventListener('mouseup', this.handleMouseUp);
            // Add dragging class for visual feedback
            this.style.cursor = 'grabbing';
        }
        /**
         * Checks if the click is on padding area (not on text content)
         */
        isClickOnPadding(event, element) {
            const rect = element.getBoundingClientRect();
            const clickX = event.clientX - rect.left;
            const clickY = event.clientY - rect.top;
            // Check if click is in padding areas (first/last 16px of padding)
            const paddingThreshold = 16;
            return (clickX < paddingThreshold ||
                clickX > rect.width - paddingThreshold ||
                clickY < paddingThreshold ||
                clickY > rect.height - paddingThreshold);
        }
        /**
         * Handles mouse movement during drag operation.
         */
        handleMouseMove = (event) => {
            if (!this.isDragging)
                return;
            // Calculate new position
            const newX = event.clientX - this.dragOffset.x;
            const newY = event.clientY - this.dragOffset.y;
            // Get viewport dimensions
            const viewportWidth = window.innerWidth;
            const viewportHeight = window.innerHeight;
            const rect = this.getBoundingClientRect();
            // Constrain to viewport bounds
            const constrainedX = Math.max(0, Math.min(newX, viewportWidth - rect.width));
            const constrainedY = Math.max(0, Math.min(newY, viewportHeight - rect.height));
            // Update position
            this.position = { x: constrainedX, y: constrainedY };
            this.style.left = `${constrainedX}px`;
            this.style.top = `${constrainedY}px`;
            this.style.right = 'auto'; // Override the CSS right positioning
        };
        /**
         * Handles the end of a drag operation.
         */
        handleMouseUp = () => {
            if (!this.isDragging)
                return;
            this.isDragging = false;
            this.style.cursor = '';
            // Remove global event listeners
            document.removeEventListener('mousemove', this.handleMouseMove);
            document.removeEventListener('mouseup', this.handleMouseUp);
        };
        connectedCallback() {
            super.connectedCallback();
            // Set up popover behavior
            this.setAttribute('popover', 'manual');
            // Listen for popover toggle events
            this.addEventListener('toggle', this.handlePopoverToggle);
        }
        firstUpdated() {
            // Set up scroll listener for scroll shadows
            const contentWrapper = this.shadowRoot?.querySelector('.content-wrapper');
            if (contentWrapper) {
                // Initial scroll state check
                this.updateScrollShadows(contentWrapper);
            }
        }
        /**
         * Updates scroll shadow opacity based on scroll position
         */
        handleScroll = (event) => {
            const element = event.target;
            this.updateScrollShadows(element);
        };
        updateScrollShadows(element) {
            const { scrollTop, scrollHeight, clientHeight } = element;
            const maxScroll = scrollHeight - clientHeight;
            // Calculate scroll shadow opacity (0-1)
            const scrollTopOpacity = Math.min(scrollTop / 20, 1); // Fade in over first 20px
            const scrollBottomOpacity = Math.min((maxScroll - scrollTop) / 20, 1); // Fade out over last 20px
            // Only show bottom shadow if content is actually scrollable
            const bottomOpacity = maxScroll > 0 ? Math.min(scrollBottomOpacity, 1) : 0;
            // Update CSS custom properties
            element.style.setProperty('--scroll-top', scrollTopOpacity.toString());
            element.style.setProperty('--scroll-bottom', bottomOpacity.toString());
            // Update host attribute for header styling
            if (scrollTop > 5) {
                this.setAttribute('data-scrolled', '');
            }
            else {
                this.removeAttribute('data-scrolled');
            }
        }
        disconnectedCallback() {
            super.disconnectedCallback();
            // Clean up event listeners
            document.removeEventListener('mousemove', this.handleMouseMove);
            document.removeEventListener('mouseup', this.handleMouseUp);
            this.removeEventListener('toggle', this.handlePopoverToggle);
        }
        render() {
            if (!this.topic) {
                return nothing;
            }
            return html `
      <div class="header" @mousedown="${this.handleMouseDown}">
        <span class="title">${this.topic.title}</span>
        <ui-icon-button @click="${this.handleClose}" aria-label="Close help panel">
          <ui-icon>close</ui-icon>
        </ui-icon-button>
      </div>
      <div class="content-wrapper" @mousedown="${this.handleMouseDown}" @scroll="${this.handleScroll}">
        <div class="content">
          ${this.renderMarkdown(this.topic.body)} ${this.renderExamples(this.topic.examples)}
          ${this.topic.links && this.topic.links.length > 0
                ? html `
                <div class="links">
                  <h3>Related Links</h3>
                  <ul>
                    ${this.topic.links.map((link) => html `<li>
                          <a href="${link.url}" target="_blank" rel="noopener noreferrer"
                            >${link.text}
                            <ui-icon style="font-size: 1em; vertical-align: middle;">open_in_new</ui-icon></a
                          >
                        </li>`)}
                  </ul>
                </div>
              `
                : nothing}
        </div>
      </div>
    `;
        }
        /**
         * Renders examples section, handling both string and array formats
         */
        renderExamples(examples) {
            if (!examples) {
                return nothing;
            }
            // Handle legacy string format
            if (typeof examples === 'string') {
                return html `<h3>Examples</h3>
        ${this.renderMarkdown(examples)}`;
            }
            // Handle new array format
            if (Array.isArray(examples) && examples.length > 0) {
                return html `
        <h3>Examples</h3>
        ${examples.map((example) => html `
            ${example.title ? html `<h4>${example.title}</h4>` : nothing} ${this.renderMarkdown(example.value)}
          `)}
      `;
            }
            return nothing;
        }
        static {
            __runInitializers(_classThis, _classExtraInitializers);
        }
    };
    return HelpPanel = _classThis;
})();
export { HelpPanel };
//# sourceMappingURL=help_panel.js.map