// Copyright 2025 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import './file_thumbnail.js';
import { CrLitElement } from '//resources/lit/v3_0/lit.rollup.js';
import { getCss } from './file_carousel.css.js';
import { getHtml } from './file_carousel.html.js';
const DEBOUNCE_TIMEOUT_MS = 20;
const CAROUSEL_HEIGHT_PADDING = 18;
function debounce(context, func, delay) {
    let timeout;
    return function (...args) {
        clearTimeout(timeout);
        timeout = setTimeout(() => func.apply(context, args), delay);
    };
}
export class ComposeboxFileCarouselElement extends CrLitElement {
    static get is() {
        return 'cr-composebox-file-carousel';
    }
    static get styles() {
        return getCss();
    }
    render() {
        return getHtml.bind(this)();
    }
    static get properties() {
        return {
            files: { type: Array },
            enableScrolling: {
                type: Boolean,
                reflect: true,
            },
            gradientTopHidden_: {
                type: Boolean,
                reflect: true,
                attribute: 'gradient-top-hidden',
            },
            gradientBottomHidden_: {
                type: Boolean,
                reflect: true,
                attribute: 'gradient-bottom-hidden',
            },
        };
    }
    #files_accessor_storage = [];
    get files() { return this.#files_accessor_storage; }
    set files(value) { this.#files_accessor_storage = value; }
    #enableScrolling_accessor_storage = false;
    get enableScrolling() { return this.#enableScrolling_accessor_storage; }
    set enableScrolling(value) { this.#enableScrolling_accessor_storage = value; }
    #gradientTopHidden__accessor_storage = false;
    get gradientTopHidden_() { return this.#gradientTopHidden__accessor_storage; }
    set gradientTopHidden_(value) { this.#gradientTopHidden__accessor_storage = value; }
    #gradientBottomHidden__accessor_storage = false;
    get gradientBottomHidden_() { return this.#gradientBottomHidden__accessor_storage; }
    set gradientBottomHidden_(value) { this.#gradientBottomHidden__accessor_storage = value; }
    resizeObserver_ = null;
    mutationObserver_ = null;
    fileCarouselContainer_ = null;
    getThumbnailElementByUuid(uuid) {
        const thumbnails = this.shadowRoot.querySelectorAll('cr-composebox-file-thumbnail');
        for (const thumbnail of thumbnails) {
            if (thumbnail.file.uuid === uuid) {
                return thumbnail;
            }
        }
        return null;
    }
    connectedCallback() {
        super.connectedCallback();
        this.resizeObserver_ = new ResizeObserver(debounce(this, () => {
            const height = this.clientHeight ? this.clientHeight + CAROUSEL_HEIGHT_PADDING : 0;
            this.fire('carousel-resize', { height: height });
        }, DEBOUNCE_TIMEOUT_MS));
        this.resizeObserver_.observe(this);
    }
    disconnectedCallback() {
        super.disconnectedCallback();
        if (this.resizeObserver_) {
            this.resizeObserver_.disconnect();
            this.resizeObserver_ = null;
        }
        if (this.mutationObserver_) {
            this.mutationObserver_.disconnect();
            this.mutationObserver_ = null;
        }
        if (this.fileCarouselContainer_) {
            this.fileCarouselContainer_.removeEventListener('scroll', this.toggleGradient);
        }
    }
    updated(changedProperties) {
        super.updated(changedProperties);
        if (changedProperties.has('enableScrolling')) {
            this.initializeOrUpdateObservers_();
        }
        // Scroll to the bottom when files are added.
        if (this.enableScrolling && changedProperties.has('files')) {
            const oldFiles = changedProperties.get('files');
            // `oldFiles` is undefined on the component's first render. We only want
            // to scroll when files are added after the component has been rendered.
            if (oldFiles && this.files.length > oldFiles.length) {
                this.scrollToBottom();
            }
        }
    }
    async initializeOrUpdateObservers_() {
        if (this.mutationObserver_) {
            this.mutationObserver_.disconnect();
            this.mutationObserver_ = null;
        }
        if (this.fileCarouselContainer_) {
            this.fileCarouselContainer_.removeEventListener('scroll', this.toggleGradient);
        }
        if (!this.enableScrolling) {
            return;
        }
        await this.updateComplete;
        this.fileCarouselContainer_ =
            this.shadowRoot.querySelector('.file-carousel-container');
        if (this.fileCarouselContainer_) {
            this.toggleGradient = this.toggleGradient.bind(this);
            this.fileCarouselContainer_.addEventListener('scroll', this.toggleGradient);
            this.mutationObserver_ = new MutationObserver(() => {
                this.toggleGradient();
            });
            this.mutationObserver_.observe(this.fileCarouselContainer_, { childList: true });
            this.toggleGradient();
        }
    }
    toggleGradient() {
        if (!this.fileCarouselContainer_) {
            return;
        }
        const el = this.fileCarouselContainer_;
        const hasScrollbar = el.scrollHeight > el.clientHeight;
        if (!hasScrollbar) {
            this.gradientTopHidden_ = true;
            this.gradientBottomHidden_ = true;
            return;
        }
        const isScrolledToTop = el.scrollTop === 0;
        this.gradientTopHidden_ = isScrolledToTop;
        // Epsilon comparison to handle non-integer values.
        const isScrolledToBottom = Math.abs(el.scrollHeight - el.clientHeight - el.scrollTop) < 1;
        this.gradientBottomHidden_ = isScrolledToBottom;
    }
    scrollToBottom() {
        if (this.fileCarouselContainer_) {
            this.fileCarouselContainer_.scrollTo({
                top: this.fileCarouselContainer_.scrollHeight,
                behavior: 'smooth',
            });
        }
    }
}
customElements.define(ComposeboxFileCarouselElement.is, ComposeboxFileCarouselElement);
