// Copyright 2024 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import { getToastManager } from 'chrome://resources/cr_elements/cr_toast/cr_toast_manager.js';
import { assert, assertNotReached, assertNotReachedCase } from 'chrome://resources/js/assert.js';
import { loadTimeData } from 'chrome://resources/js/load_time_data.js';
import { TOAST_DURATION_MS } from './item_util.js';
export const ItemMixin = (superClass) => {
    class ItemMixin extends superClass {
        static get properties() {
            return {
                /**
                 * The underlying ExtensionInfo for the details being displayed.
                 */
                data: { type: Object },
                /* The item's delegate, or null. */
                delegate: { type: Object },
            };
        }
        #data_accessor_storage;
        get data() { return this.#data_accessor_storage; }
        set data(value) { this.#data_accessor_storage = value; }
        #delegate_accessor_storage;
        get delegate() { return this.#delegate_accessor_storage; }
        set delegate(value) { this.#delegate_accessor_storage = value; }
        /**
         * Prevents reloading the same item while it's already being reloaded.
         */
        isReloading_ = false;
        /**
         * @return The app or extension label depending on |type|.
         */
        appOrExtension(type, appLabel, extensionLabel) {
            const ExtensionType = chrome.developerPrivate.ExtensionType;
            switch (type) {
                case ExtensionType.HOSTED_APP:
                case ExtensionType.LEGACY_PACKAGED_APP:
                case ExtensionType.PLATFORM_APP:
                    return appLabel;
                case ExtensionType.EXTENSION:
                case ExtensionType.SHARED_MODULE:
                    return extensionLabel;
                case ExtensionType.THEME:
                    assertNotReached('Don\'t send themes to the chrome://extensions page');
                default:
                    assertNotReachedCase(type, 'Item type is not App or Extension.');
            }
        }
        /**
         * @return The a11y association descriptor, e.g. "Related to <ext>".
         */
        a11yAssociation(name) {
            // Don't use I18nMixin.i18n because of additional checks it
            // performs. Lit ensures that this string is not stamped into
            // arbitrary HTML. `name` can contain any data including html tags,
            // e.g. "My <video> download extension!"
            return loadTimeData.getStringF('extensionA11yAssociation', name);
        }
        /**
         * Checks if this is an unpacked or disabled item that can be reloaded.
         *
         * @returns If the item can be reloaded.
         */
        canReloadItem() {
            // Only display the reload spinner if the extension is unpacked and
            // enabled or disabled for reload. If an extension fails to reload
            // (due to e.g. a parsing error), it will remain disabled with the
            // "reloading" reason. We show the reload button when it's disabled
            // for reload to enable developers to reload the fixed version. (Note
            // that trying to reload an extension that is currently trying to
            // reload is a no-op.) For other disableReasons, there's no point in
            // reloading a disabled extension, and we'll show a crashed reload
            // button if it's terminated.
            if (!this.data) {
                return false;
            }
            const showIcon = this.data.location === chrome.developerPrivate.Location.UNPACKED &&
                (this.data.state === chrome.developerPrivate.ExtensionState.ENABLED ||
                    this.data.disableReasons.reloading);
            return showIcon;
        }
        /**
         * Reloads the item.
         */
        async reloadItem() {
            // Don't reload if in the middle of an update.
            if (this.isReloading_) {
                return;
            }
            this.isReloading_ = true;
            const toastManager = getToastManager();
            // Keep the toast open indefinitely.
            toastManager.duration = 0;
            toastManager.show(loadTimeData.getString('itemReloading'));
            assert(this.delegate);
            assert(this.data);
            try {
                await this.delegate.reloadItem(this.data.id);
                toastManager.hide();
                toastManager.duration = TOAST_DURATION_MS;
                toastManager.show(loadTimeData.getString('itemReloaded'));
            }
            catch (loadError) {
                toastManager.hide();
                throw loadError;
            }
            finally {
                this.isReloading_ = false;
            }
        }
    }
    return ItemMixin;
};
