// Copyright 2026 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import './pinned_toolbar_action.js';
import './toolbar_divider.js';
import { CrLitElement } from '//resources/lit/v3_0/lit.rollup.js';
import { PinnedToolbarAction } from '/shared/toolbar_ui_api_data_model.mojom-webui.js';
import { getCss } from './pinned_toolbar_actions.css.js';
import { getHtml } from './pinned_toolbar_actions.html.js';
export class PinnedToolbarActionsElement extends CrLitElement {
    static get is() {
        return 'pinned-toolbar-actions';
    }
    static get styles() {
        return getCss();
    }
    render() {
        return getHtml.bind(this)();
    }
    static get properties() {
        return {
            state: { type: Array },
            keyedStates_: { type: Array },
        };
    }
    #state_accessor_storage = [];
    get state() { return this.#state_accessor_storage; }
    set state(value) { this.#state_accessor_storage = value; }
    #keyedStates__accessor_storage = [];
    // Internal reactive state that includes exiting items.
    get keyedStates_() { return this.#keyedStates__accessor_storage; }
    set keyedStates_(value) { this.#keyedStates__accessor_storage = value; }
    willUpdate(changedProperties) {
        super.willUpdate(changedProperties);
        const changedPrivateProperties = changedProperties;
        if (changedPrivateProperties.has('state')) {
            this.reconcileKeys_();
        }
    }
    firstUpdated(changedProperties) {
        super.firstUpdated(changedProperties);
        // Add listener to shadow root to catch bubbled transitionend and
        // transitioncancel events.
        this.shadowRoot.addEventListener('transitionend', (e) => this.onTransitionDone_(e));
        this.shadowRoot.addEventListener('transitioncancel', (e) => this.onTransitionDone_(e));
    }
    reconcileKeys_() {
        const newMojoStates = this.state || [];
        // 1. Map new mojo states to KeyedActionState (all active).
        let dividerCount = 0;
        const newKeyedStates = newMojoStates.map(s => {
            const key = s.action === PinnedToolbarAction.kDivider ?
                `divider-${dividerCount++}` :
                s.action.toString();
            return { key, state: s };
        });
        if (this.keyedStates_.length === 0) {
            this.keyedStates_ = newKeyedStates;
            this.updateVisibility_();
            return;
        }
        // 2. Find which keys were in the old `keyedStates_` but are not in
        // `newKeyedStates`. These are the ones that are "sliding-out".
        const newKeys = new Set(newKeyedStates.map(s => s.key));
        const missingOldStates = this.keyedStates_.filter(s => !newKeys.has(s.key));
        // 3. Re-insert "sliding-out" states (marked as exiting) into their old
        // positions in `keyedStates_` so they'll be rendered while "sliding-out"
        // if animations are enabled.
        const showAnimations = getComputedStyle(this)
            .getPropertyValue('--animations-enabled')
            .trim() !== '0';
        if (showAnimations) {
            // Sort missing states by their original index to preserve order during
            // insertion
            const oldKeyToIndex = new Map(this.keyedStates_.map((s, i) => [s.key, i]));
            missingOldStates.sort((a, b) => oldKeyToIndex.get(a.key) - oldKeyToIndex.get(b.key));
            // Insert them back with `exiting` set to true.
            for (const missing of missingOldStates) {
                const exitingState = { ...missing, exiting: true };
                const originalIndex = oldKeyToIndex.get(missing.key);
                const insertIndex = Math.min(originalIndex, newKeyedStates.length);
                newKeyedStates.splice(insertIndex, 0, exitingState);
            }
        }
        this.keyedStates_ = newKeyedStates;
        this.updateVisibility_();
        // If the layout engine has already forced the exiting elements to 0 width
        // (preempting the transition), or if animations are disabled, remove them
        // immediately.
        this.updateComplete.then(() => {
            for (const el of this.shadowRoot.querySelectorAll('.exiting')) {
                const htmlEl = el;
                // If it's already 0px wide, it won't transition.
                if (htmlEl.getBoundingClientRect().width === 0) {
                    const key = htmlEl.dataset['key'];
                    if (key) {
                        this.keyedStates_ = this.keyedStates_.filter(s => s.key !== key);
                    }
                }
            }
            this.updateVisibility_();
        });
    }
    // When an element finishes "sliding-out", remove it from `keyedStates_`.
    onTransitionDone_(e) {
        // We only care about the width transition to trigger removal
        if (e.propertyName !== 'width') {
            return;
        }
        const target = e.target;
        if (!target.classList.contains('exiting')) {
            return;
        }
        const key = target.dataset['key'];
        if (!key) {
            return;
        }
        // Remove the finished item (automatically triggers update)
        this.keyedStates_ = this.keyedStates_.filter(s => s.key !== key);
        this.updateVisibility_();
    }
    updateVisibility_() {
        this.hidden = this.keyedStates_.length === 0;
    }
}
customElements.define(PinnedToolbarActionsElement.is, PinnedToolbarActionsElement);
