// Copyright 2019 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
/* eslint-disable @devtools/no-imperative-dom-api */

import './Toolbar.js';

import * as Common from '../../core/common/common.js';
import * as Host from '../../core/host/host.js';
import * as i18n from '../../core/i18n/i18n.js';
import * as Platform from '../../core/platform/platform.js';
import * as Root from '../../core/root/root.js';
import type * as Foundation from '../../foundation/foundation.js';
import {createIcon} from '../kit/kit.js';
import {render, type TemplateResult} from '../lit/lit.js';
import * as VisualLogging from '../visual_logging/visual_logging.js';

import * as ARIAUtils from './ARIAUtils.js';
import type {ContextMenu} from './ContextMenu.js';
import * as PlusButton from './PlusButton.js';
import {StackedPane} from './StackedPane.js';
import {type EventData, Events as TabbedPaneEvents, TabbedPane} from './TabbedPane.js';
import {type ItemsProvider, type ToolbarItem, ToolbarMenuButton} from './Toolbar.js';
import type {TabbedViewLocation, View, ViewLocation} from './View.js';
import {
  getLocalizedViewLocationCategory,
  getRegisteredLocationResolvers,
  getRegisteredViewExtensions,
  maybeRemoveViewExtension,
  registerLocationResolver,
  registerViewExtension,
  resetViewRegistration,
  ViewLocationCategory,
  ViewLocationValues,
  ViewPersistence,
  type ViewRegistration,
} from './ViewRegistration.js';
import {type AnyWidget, VBox, type Widget} from './Widget.js';

const UIStrings = {
  /**
   * @description Accessible label for a panel view container.
   * @example {Sensors} PH1
   */
  sPanel: '{PH1} panel',
} as const;
const str_ = i18n.i18n.registerUIStrings('ui/legacy/ViewManager.ts', UIStrings);
const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);

export const defaultOptionsForTabs = {
  security: true,
  freestyler: true,
};

type TabbedPaneFactory = () => TabbedPane;

export class PreRegisteredView implements View {
  private readonly viewRegistration: ViewRegistration;
  private readonly universe?: Foundation.Universe.Universe;
  private widgetPromise: Promise<AnyWidget>|null;

  constructor(viewRegistration: ViewRegistration, universe?: Foundation.Universe.Universe) {
    this.viewRegistration = viewRegistration;
    this.universe = universe;
    this.widgetPromise = null;
  }

  title(): Common.UIString.LocalizedString {
    return this.viewRegistration.title();
  }

  commandPrompt(): Common.UIString.LocalizedString {
    return this.viewRegistration.commandPrompt();
  }
  isCloseable(): boolean {
    return this.viewRegistration.persistence === ViewPersistence.CLOSEABLE;
  }

  isPreviewFeature(): boolean {
    return Boolean(this.viewRegistration.isPreviewFeature);
  }

  featurePromotionId(): string|undefined {
    return this.viewRegistration.featurePromotionId;
  }

  iconName(): string|undefined {
    return this.viewRegistration.iconName;
  }

  isTransient(): boolean {
    return this.viewRegistration.persistence === ViewPersistence.TRANSIENT;
  }

  viewId(): string {
    return this.viewRegistration.id;
  }

  location(): ViewLocationValues|undefined {
    return this.viewRegistration.location;
  }

  order(): number|undefined {
    return this.viewRegistration.order;
  }

  settings(): string[]|undefined {
    return this.viewRegistration.settings;
  }

  tags(): string|undefined {
    if (this.viewRegistration.tags) {
      // Get localized keys and separate by null character to prevent fuzzy matching from matching across them.
      return this.viewRegistration.tags.map(tag => tag()).join('\0');
    }
    return undefined;
  }

  persistence(): ViewPersistence|undefined {
    return this.viewRegistration.persistence;
  }

  async toolbarItems(): Promise<ToolbarItem[]|TemplateResult> {
    if (!this.viewRegistration.hasToolbar) {
      return [];
    }
    const provider = await this.widget() as unknown as ItemsProvider;
    return provider.toolbarItems();
  }

  widget(): Promise<AnyWidget> {
    if (this.widgetPromise === null) {
      if (!this.universe) {
        throw new Error('Creating views via ViewManager requires a Foundation.Universe');
      }
      this.widgetPromise = this.viewRegistration.loadView(this.universe);
    }
    return this.widgetPromise;
  }

  async disposeView(): Promise<void> {
    if (this.widgetPromise === null) {
      return;
    }

    const widget = await this.widgetPromise;
    await widget.ownerViewDisposed();
  }

  experiment(): string|undefined {
    return this.viewRegistration.experiment;
  }

  condition(): Root.Runtime.Condition|undefined {
    return this.viewRegistration.condition;
  }
}

let viewManagerInstance: ViewManager|undefined;

export const enum Events {
  VIEW_VISIBILITY_CHANGED = 'ViewVisibilityChanged',
}

export interface ViewVisibilityEventData {
  location: string;
  revealedViewId: string|undefined;
  hiddenViewId: string|undefined;
}

export interface EventTypes {
  [Events.VIEW_VISIBILITY_CHANGED]: ViewVisibilityEventData;
}

export class ViewManager extends Common.ObjectWrapper.ObjectWrapper<EventTypes> {
  readonly views: Map<string, View> = new Map<string, View>();
  private readonly locationNameByViewId = new Map<string, string>();
  private readonly locationOverrideSetting: Common.Settings.Setting<Record<string, string>>;

  private readonly preRegisteredViews: PreRegisteredView[] = [];

  // TODO(crbug.com/458180550): Pass the universe unconditionally once tests no longer rely
  //   on `instance()` to create ViewManagers lazily in after/afterEach blocks.
  private constructor(universe?: Foundation.Universe.Universe) {
    super();

    // Read override setting for location
    this.locationOverrideSetting = Common.Settings.Settings.instance().createSetting('views-location-override', {});
    const preferredExtensionLocations = this.locationOverrideSetting.get();

    // Views may define their initial ordering within a location. When the user has not reordered, we use the
    // default ordering as defined by the views themselves.

    const viewsByLocation = new Map<ViewLocationValues|'none', PreRegisteredView[]>();
    for (const view of getRegisteredViewExtensions()) {
      const location = view.location || 'none';
      const views = viewsByLocation.get(location) || [];
      views.push(new PreRegisteredView(view, universe));
      viewsByLocation.set(location, views);
    }

    let sortedViewExtensions: PreRegisteredView[] = [];
    for (const views of viewsByLocation.values()) {
      views.sort((firstView, secondView) => {
        const firstViewOrder = firstView.order();
        const secondViewOrder = secondView.order();
        if (firstViewOrder !== undefined && secondViewOrder !== undefined) {
          return firstViewOrder - secondViewOrder;
        }
        return 0;
      });
      sortedViewExtensions = sortedViewExtensions.concat(views);
    }

    for (const view of sortedViewExtensions) {
      const viewId = view.viewId();
      const location = view.location();
      if (this.views.has(viewId)) {
        throw new Error(`Duplicate view id '${viewId}'`);
      }
      if (!Platform.StringUtilities.isExtendedKebabCase(viewId)) {
        throw new Error(`Invalid view ID '${viewId}'`);
      }
      this.views.set(viewId, view);
      this.preRegisteredViews.push(view);
      // Use the preferred user location if available
      const locationName = preferredExtensionLocations[viewId] || location;
      this.locationNameByViewId.set(viewId, locationName as string);
    }
  }

  static instance(opts: {
    forceNew: boolean|null,
    universe?: Foundation.Universe.Universe,
  } = {forceNew: null}): ViewManager {
    const {forceNew, universe} = opts;
    if (!viewManagerInstance || forceNew) {
      viewManagerInstance = new ViewManager(universe);
    }

    return viewManagerInstance;
  }

  static removeInstance(): void {
    viewManagerInstance = undefined;
  }

  static createToolbar(toolbarItems: ToolbarItem[]|TemplateResult): Element|null {
    if (Array.isArray(toolbarItems) && !toolbarItems.length) {
      return null;
    }
    const toolbar = document.createElement('devtools-toolbar');
    if (Array.isArray(toolbarItems)) {
      for (const item of toolbarItems) {
        toolbar.appendToolbarItem(item);
      }
    } else {
      // eslint-disable-next-line @devtools/no-lit-render-outside-of-view
      render(toolbarItems, toolbar);
    }
    return toolbar;
  }

  static setWidgetForView(view: View, widget: AnyWidget): void {
    widgetForView.set(view, widget);
  }

  getRegisteredViewExtensions(): PreRegisteredView[] {
    return this.preRegisteredViews;
  }

  locationNameForViewId(viewId: string): string {
    const locationName = this.locationNameByViewId.get(viewId);
    if (!locationName) {
      throw new Error(`No location name for view with id ${viewId}`);
    }
    return locationName;
  }

  /**
   * Moves a view to a new location
   */
  moveView(viewId: string, locationName: string, options?: {
    shouldSelectTab: (boolean),
    overrideSaving: (boolean),
  }): void {
    const defaultOptions = {shouldSelectTab: true, overrideSaving: false};
    const {shouldSelectTab, overrideSaving} = options || defaultOptions;
    if (!viewId || !locationName) {
      return;
    }

    const view = this.view(viewId);
    if (!view) {
      return;
    }

    if (!overrideSaving) {
      // Update the inner map of locations
      this.locationNameByViewId.set(viewId, locationName);

      // Update the settings of location overwrites
      const locations = this.locationOverrideSetting.get();
      locations[viewId] = locationName;
      this.locationOverrideSetting.set(locations);
    }

    // Find new location and show view there
    void this.resolveLocation(locationName).then(location => {
      if (!location) {
        throw new Error('Move view: Could not resolve location for view: ' + viewId);
      }
      location.reveal();
      return location.showView(view, undefined, /* userGesture*/ true, /* omitFocus*/ false, shouldSelectTab);
    });
  }

  revealView(view: View): Promise<void> {
    const location = locationForView.get(view);
    if (!location) {
      return Promise.resolve();
    }
    location.reveal();
    return location.showView(view);
  }

  /**
   * Show view in location
   */
  showViewInLocation(viewId: string, locationName: string, shouldSelectTab: boolean|undefined = true): void {
    this.moveView(viewId, locationName, {
      shouldSelectTab,
      overrideSaving: true,
    });
  }

  view(viewId: string): View {
    const view = this.views.get(viewId);
    if (!view) {
      throw new Error(`No view with id ${viewId} found!`);
    }
    return view;
  }

  materializedWidget<T extends HTMLElement|DocumentFragment = HTMLElement>(viewId: string): Widget<T>|null {
    const view = this.views.get(viewId);
    if (!view) {
      return null;
    }
    return (widgetForView.get(view) as Widget<T>| undefined) || null;
  }

  hasView(viewId: string): boolean {
    return this.views.has(viewId);
  }

  async showView(viewId: string, userGesture?: boolean, omitFocus?: boolean): Promise<void> {
    const view = this.views.get(viewId);
    if (!view) {
      console.error('Could not find view for id: \'' + viewId + '\' ' + new Error().stack);
      return;
    }

    const location = locationForView.get(view) ?? await this.resolveLocation(this.locationNameByViewId.get(viewId));
    if (!location) {
      throw new Error('Could not resolve location for view: ' + viewId);
    }
    location.reveal();
    await location.showView(view, undefined, userGesture, omitFocus);
  }

  isViewVisible(viewId: string): boolean {
    const view = this.views.get(viewId);
    if (!view) {
      return false;
    }

    const location = locationForView.get(view);
    if (!location) {
      return false;
    }

    return location.isViewVisible(view);
  }

  async resolveLocation(location?: string): Promise<Location|null> {
    if (!location) {
      return null;
    }
    const registeredResolvers = getRegisteredLocationResolvers().filter(resolver => resolver.name === location);

    if (registeredResolvers.length > 1) {
      throw new Error('Duplicate resolver for location: ' + location);
    }
    if (registeredResolvers.length) {
      const resolver = await registeredResolvers[0].loadResolver();
      return resolver.resolveLocation(location) as Location | null;
    }
    throw new Error('Unresolved location: ' + location);
  }

  createTabbedLocation(
      revealCallback: (() => void), location: string, restoreSelection?: boolean, allowReorder?: boolean,
      options?: TabbedLocationOptions): TabbedViewLocation {
    return new TabbedLocation(this, revealCallback, location, restoreSelection, allowReorder, options);
  }

  createStackLocation(revealCallback?: (() => void), location?: string, jslogContext?: string): StackLocation {
    return new StackLocation(this, revealCallback, location, jslogContext);
  }

  hasViewsForLocation(location: string): boolean {
    return Boolean(this.viewsForLocation(location).length);
  }

  viewsForLocation(location: string): View[] {
    const result = [];
    for (const [id, view] of this.views.entries()) {
      if (this.locationNameByViewId.get(id) === location) {
        result.push(view);
      }
    }
    return result;
  }
}

const widgetForView = new WeakMap<View, AnyWidget>();

export class ContainerWidget extends VBox {
  private readonly view: View;
  private materializePromise?: Promise<void>;

  constructor(view: View) {
    super();
    this.element.classList.add('flex-auto', 'view-container', 'overflow-auto');
    this.view = view;
    this.element.tabIndex = -1;
    ARIAUtils.markAsTabpanel(this.element);
    ARIAUtils.setLabel(this.element, i18nString(UIStrings.sPanel, {PH1: view.title()}));
    this.setDefaultFocusedElement(this.element);
  }

  materialize(): Promise<void> {
    if (this.materializePromise) {
      return this.materializePromise;
    }
    const promises = [];
    // TODO(crbug.com/1006759): Transform to async-await
    promises.push(this.view.toolbarItems().then(toolbarItems => {
      const toolbarElement = ViewManager.createToolbar(toolbarItems);
      if (toolbarElement) {
        this.element.insertBefore(toolbarElement, this.element.firstChild);
      }
    }));
    promises.push(this.view.widget().then(widget => {
      // Move focus from |this| to loaded |widget| if any.
      const shouldFocus = this.element.hasFocus();
      this.setDefaultFocusedElement(null);
      ViewManager.setWidgetForView(this.view, widget);
      widget.show(this.element);
      if (shouldFocus) {
        widget.focus();
      }
    }));
    this.materializePromise = Promise.all(promises).then(() => {});
    return this.materializePromise;
  }

  override wasShown(): void {
    super.wasShown();
    void this.materialize().then(() => {
      const widget = widgetForView.get(this.view);
      if (widget) {
        widget.show(this.element);
        this.wasShownForTest();
      }
    });
  }

  private wasShownForTest(): void {
    // This method is sniffed in tests.
  }
}

class Location {
  protected readonly manager: ViewManager;
  private readonly revealCallback: (() => void)|undefined;
  readonly #widget: AnyWidget;

  constructor(manager: ViewManager, widget: AnyWidget, revealCallback?: (() => void)) {
    this.manager = manager;
    this.revealCallback = revealCallback;
    this.#widget = widget;
  }

  widget(): AnyWidget {
    return this.#widget;
  }

  reveal(): void {
    if (this.revealCallback) {
      this.revealCallback();
    }
  }

  showView(
      _view: View, _insertBefore?: View|null, _userGesture?: boolean, _omitFocus?: boolean,
      _shouldSelectTab?: boolean): Promise<void> {
    throw new Error('not implemented');
  }

  removeView(_view: View): void {
    throw new Error('not implemented');
  }

  isViewVisible(_view: View): boolean {
    throw new Error('not implemented');
  }
}

const locationForView = new WeakMap<View, Location>();

type CloseableTabSetting = Record<string, boolean>;

type TabOrderSetting = Record<string, number>;

export interface TabbedLocationOptions {
  defaultTab?: string|null;
  isLocationVisible?: () => boolean;
  tabbedPaneFactory?: TabbedPaneFactory;
  /**
   * Installed into the `TabbedPane`'s `trailing-button` slot before any
   * tabs are appended, so the very first layout pass reserves width for it.
   */
  plusButton?: PlusButton.PlusButtonOptions;
}

class TabbedLocation extends Location implements TabbedViewLocation {
  #tabbedPane: TabbedPane;
  private readonly location: string;
  private readonly allowReorder: boolean|undefined;
  private readonly closeableTabSetting: Common.Settings.Setting<CloseableTabSetting>;
  private readonly tabOrderSetting: Common.Settings.Setting<TabOrderSetting>;
  private readonly lastSelectedTabSetting?: Common.Settings.Setting<string>;
  private readonly defaultTab: string|null|undefined;
  private readonly isLocationVisible: (() => boolean)|undefined;
  private readonly views = new Map<string, View>();

  constructor(
      manager: ViewManager, revealCallback: (() => void), location: string, restoreSelection?: boolean,
      allowReorder?: boolean, options?: TabbedLocationOptions) {
    const tabbedPane = options?.tabbedPaneFactory ? options.tabbedPaneFactory() : new TabbedPane();
    if (allowReorder) {
      tabbedPane.setAllowTabReorder(true);
    }

    super(manager, tabbedPane, revealCallback);
    this.location = location;
    this.#tabbedPane = tabbedPane;
    this.allowReorder = allowReorder;

    this.#tabbedPane.addEventListener(TabbedPaneEvents.TabSelected, this.tabSelected, this);
    this.#tabbedPane.addEventListener(TabbedPaneEvents.TabClosed, this.tabClosed, this);
    this.#tabbedPane.addEventListener(TabbedPaneEvents.PaneVisibilityChanged, this.tabbedPaneVisibilityChanged, this);

    this.closeableTabSetting = Common.Settings.Settings.instance().createSetting('closeable-tabs', {});
    // As we give tabs the capability to be closed we also need to add them to the setting so they are still open
    // until the user decide to close them
    this.setOrUpdateCloseableTabsSetting();

    this.tabOrderSetting = Common.Settings.Settings.instance().createSetting(location + '-tab-order', {});
    this.#tabbedPane.addEventListener(TabbedPaneEvents.TabOrderChanged, this.persistTabOrder, this);
    if (restoreSelection) {
      this.lastSelectedTabSetting = Common.Settings.Settings.instance().createSetting(location + '-selected-tab', '');
    }
    this.defaultTab = options?.defaultTab;
    this.isLocationVisible = options?.isLocationVisible;

    // Install before `appendApplicableItems` so the very first layout pass
    // reserves width for the button and we avoid a reflow that snaps the
    // last tab into the overflow menu.
    if (options?.plusButton && Root.Runtime.hostConfig.devToolsPlusButton?.enabled) {
      PlusButton.installPlusButton(
          {
            tabbedPane: this.#tabbedPane,
            location: this.location,
            // Use the local `views` map (not `manager.viewsForLocation`) so
            // cross-location moves added via `appendView` are reflected.
            views: () => this.views.values(),
            manager: this.manager,
            showView: view => {
              this.showView(view, undefined, /* userGesture */ true).catch(err => console.error(err));
            },
          },
          options.plusButton);
    }

    if (location) {
      this.appendApplicableItems(location);
    }
  }

  private setOrUpdateCloseableTabsSetting(): void {
    // Update the setting value, we respect the closed state decided by the user
    // and append the new tabs with value of true so they are shown open
    const newClosable = {
      ...defaultOptionsForTabs,
      ...this.closeableTabSetting.get(),
    };
    this.closeableTabSetting.set(newClosable);
  }

  override widget(): AnyWidget {
    return this.#tabbedPane;
  }

  tabbedPane(): TabbedPane {
    return this.#tabbedPane;
  }

  enableMoreTabsButton(): ToolbarMenuButton {
    const moreTabsButton = new ToolbarMenuButton(
        this.appendTabsToMenu.bind(this), /* isIconDropdown */ true, undefined, 'more-tabs', 'dots-vertical');
    this.#tabbedPane.leftToolbar().appendToolbarItem(moreTabsButton);
    return moreTabsButton;
  }

  appendApplicableItems(locationName: string): void {
    const views = this.manager.viewsForLocation(locationName);
    if (this.allowReorder) {
      let i = 0;
      const persistedOrders = this.tabOrderSetting.get();
      const orders = new Map<string, number>();
      for (const view of views) {
        orders.set(view.viewId(), persistedOrders[view.viewId()] || (++i) * TabbedLocation.orderStep);
      }
      views.sort((a, b) => (orders.get(a.viewId()) as number) - (orders.get(b.viewId()) as number));
    }

    for (const view of views) {
      const id = view.viewId();
      this.views.set(id, view);
      locationForView.set(view, this);
      if (view.isTransient()) {
        continue;
      }
      if (!view.isCloseable()) {
        this.appendTab(view);
      } else if (this.closeableTabSetting.get()[id]) {
        this.appendTab(view);
      }
    }

    // If a default tab was provided we open or select it
    if (this.defaultTab) {
      if (this.#tabbedPane.hasTab(this.defaultTab)) {
        // If the tabbed pane already has the tab we just have to select it
        this.#tabbedPane.selectTab(this.defaultTab);
      } else {
        // If the tab is not present already it can be because:
        // it doesn't correspond to this tabbed location
        // or because it is closed
        const view = Array.from(this.views.values()).find(view => view.viewId() === this.defaultTab);
        if (view) {
          // defaultTab is indeed part of the views for this tabbed location
          void this.showView(view);
        }
      }
    } else if (this.lastSelectedTabSetting && this.#tabbedPane.hasTab(this.lastSelectedTabSetting.get())) {
      this.#tabbedPane.selectTab(this.lastSelectedTabSetting.get());
    }
  }

  private appendTabsToMenu(contextMenu: ContextMenu): void {
    const views = Array.from(this.views.values());
    views.sort((viewa, viewb) => viewa.title().localeCompare(viewb.title()));

    for (const view of views) {
      const title = view.title();

      if (view.viewId() === 'issues-pane') {
        contextMenu.defaultSection().appendItem(title, () => {
          Host.userMetrics.issuesPanelOpenedFrom(Host.UserMetrics.IssueOpener.HAMBURGER_MENU);
          void this.showView(view, undefined, true);
        }, {jslogContext: 'issues-pane'});
        continue;
      }

      const isPreviewFeature = view.isPreviewFeature();
      contextMenu.defaultSection().appendItem(
          title, this.showView.bind(this, view, undefined, true), {isPreviewFeature, jslogContext: view.viewId()});
    }
  }

  private appendTab(view: View, index?: number): void {
    this.#tabbedPane.appendTab(
        view.viewId(), view.title(), new ContainerWidget(view), undefined, false,
        view.isCloseable() || view.isTransient(), view.isPreviewFeature(), index);
    const iconName = view.iconName();
    if (iconName) {
      const icon = createIcon(iconName);
      this.#tabbedPane.setTabIcon(view.viewId(), icon);
    }
  }

  appendView(view: View, insertBefore?: View|null): void {
    if (this.#tabbedPane.hasTab(view.viewId())) {
      return;
    }
    const oldLocation = locationForView.get(view);
    if (oldLocation && oldLocation !== this) {
      oldLocation.removeView(view);
    }
    locationForView.set(view, this);
    this.manager.views.set(view.viewId(), view);
    this.views.set(view.viewId(), view);
    let index: number|undefined = undefined;
    const tabIds = this.#tabbedPane.tabIds();
    if (this.allowReorder) {
      const orderSetting = this.tabOrderSetting.get();
      const order = orderSetting[view.viewId()];
      for (let i = 0; order && i < tabIds.length; ++i) {
        if (orderSetting[tabIds[i]] && orderSetting[tabIds[i]] > order) {
          index = i;
          break;
        }
      }
    } else if (insertBefore) {
      for (let i = 0; i < tabIds.length; ++i) {
        if (tabIds[i] === insertBefore.viewId()) {
          index = i;
          break;
        }
      }
    }
    this.appendTab(view, index);

    if (view.isCloseable()) {
      const tabs = this.closeableTabSetting.get();
      const tabId = view.viewId();
      if (!tabs[tabId]) {
        tabs[tabId] = true;
        this.closeableTabSetting.set(tabs);
      }
    }
    this.persistTabOrder();
  }

  override async showView(
      view: View, insertBefore?: View|null, userGesture?: boolean, omitFocus?: boolean,
      shouldSelectTab: boolean|undefined = true): Promise<void> {
    this.appendView(view, insertBefore);
    if (shouldSelectTab) {
      this.#tabbedPane.selectTab(view.viewId(), userGesture);
    }
    if (!omitFocus) {
      this.#tabbedPane.focus();
    }
    const widget = (this.#tabbedPane.tabView(view.viewId()) as ContainerWidget);
    await widget.materialize();
  }

  override removeView(view: View): void {
    if (!this.#tabbedPane.hasTab(view.viewId())) {
      return;
    }

    locationForView.delete(view);
    this.manager.views.delete(view.viewId());
    this.#tabbedPane.closeTab(view.viewId());
    this.views.delete(view.viewId());
  }

  override isViewVisible(view: View): boolean {
    const locationVisible = this.isLocationVisible ? this.isLocationVisible() : this.#tabbedPane.isShowing();
    return locationVisible && this.#tabbedPane.selectedTabId === view.viewId();
  }

  private tabbedPaneVisibilityChanged(event: Common.EventTarget.EventTargetEvent<{isVisible: boolean}>): void {
    if (!this.#tabbedPane.selectedTabId) {
      return;
    }
    this.manager.dispatchEventToListeners(Events.VIEW_VISIBILITY_CHANGED, {
      location: this.location,
      revealedViewId: event.data.isVisible ? this.#tabbedPane.selectedTabId : undefined,
      hiddenViewId: event.data.isVisible ? undefined : this.#tabbedPane.selectedTabId,
    });
  }

  private tabSelected(event: Common.EventTarget.EventTargetEvent<EventData>): void {
    const {tabId, prevTabId, isUserGesture} = event.data;
    if (this.lastSelectedTabSetting && isUserGesture) {
      this.lastSelectedTabSetting.set(tabId);
    }
    this.manager.dispatchEventToListeners(Events.VIEW_VISIBILITY_CHANGED, {
      location: this.location,
      revealedViewId: tabId,
      hiddenViewId: prevTabId,
    });
  }

  private tabClosed(event: Common.EventTarget.EventTargetEvent<EventData>): void {
    const {tabId} = event.data;
    const tabs = this.closeableTabSetting.get();
    if (tabs[tabId]) {
      tabs[tabId] = false;
      this.closeableTabSetting.set(tabs);
    }
    const view = this.views.get(tabId);
    if (view) {
      void view.disposeView();
    }
  }

  private persistTabOrder(): void {
    const tabIds = this.#tabbedPane.tabIds();
    const tabOrders: Record<string, number> = {};
    for (let i = 0; i < tabIds.length; i++) {
      tabOrders[tabIds[i]] = (i + 1) * TabbedLocation.orderStep;
    }

    const oldTabOrder = this.tabOrderSetting.get();
    const oldTabArray = Object.keys(oldTabOrder);
    oldTabArray.sort((a, b) => oldTabOrder[a] - oldTabOrder[b]);
    let lastOrder = 0;
    for (const key of oldTabArray) {
      if (key in tabOrders) {
        lastOrder = tabOrders[key];
        continue;
      }
      tabOrders[key] = ++lastOrder;
    }
    this.tabOrderSetting.set(tabOrders);
  }

  static orderStep = 10;  // Keep in sync with descriptors.
}

export class StackLocation extends Location implements ViewLocation {
  private readonly stackedPane: StackedPane;
  private readonly location: string;
  #isVisible: boolean;

  constructor(manager: ViewManager, revealCallback?: (() => void), location?: string, jslogContext?: string,
              initialVisibility = true) {
    const stackedPane =
        new StackedPane(ViewManager.createToolbar, ViewManager.setWidgetForView, (viewId, isExpanded) => {
          if (this.#isVisible) {
            manager.dispatchEventToListeners(Events.VIEW_VISIBILITY_CHANGED, {
              location: this.location,
              revealedViewId: isExpanded ? viewId : undefined,
              hiddenViewId: isExpanded ? undefined : viewId,
            });
          }
        });
    stackedPane.element.setAttribute('jslog', `${VisualLogging.pane(jslogContext || 'sidebar').track({resize: true})}`);
    super(manager, stackedPane, revealCallback);
    this.location = location || '';
    this.stackedPane = stackedPane;
    this.#isVisible = initialVisibility;

    if (location) {
      this.appendApplicableItems(location);
    }
  }

  // Blink test(s) rely on this
  get expandableContainers(): Map<string, AnyWidget> {
    return this.stackedPane.expandableContainers;
  }

  notifyVisibilityChanged(isVisible: boolean): void {
    if (this.#isVisible === isVisible) {
      return;
    }
    this.#isVisible = isVisible;

    for (const [viewId, container] of this.stackedPane.expandableContainers) {
      if (container.isExpanded()) {
        this.manager.dispatchEventToListeners(Events.VIEW_VISIBILITY_CHANGED, {
          location: this.location,
          revealedViewId: isVisible ? viewId : undefined,
          hiddenViewId: isVisible ? undefined : viewId,
        });
      }
    }
  }

  appendView(view: View, insertBefore?: View|null): void {
    const oldLocation = locationForView.get(view);
    if (oldLocation && oldLocation !== this) {
      oldLocation.removeView(view);
    }

    locationForView.set(view, this);
    this.manager.views.set(view.viewId(), view);
    this.stackedPane.appendView(view, insertBefore);
  }

  override async showView(view: View, insertBefore?: View|null): Promise<void> {
    this.appendView(view, insertBefore);
    await this.stackedPane.expandView(view);
  }

  override removeView(view: View): void {
    this.stackedPane.removeView(view);
    locationForView.delete(view);
    this.manager.views.delete(view.viewId());
  }

  override isViewVisible(view: View): boolean {
    return this.#isVisible && this.stackedPane.isViewExpanded(view.viewId());
  }

  appendApplicableItems(locationName: string): void {
    for (const view of this.manager.viewsForLocation(locationName)) {
      this.appendView(view);
    }
  }
}

export {
  getLocalizedViewLocationCategory,
  getRegisteredLocationResolvers,
  maybeRemoveViewExtension,
  registerLocationResolver,
  registerViewExtension,
  resetViewRegistration,
  ViewLocationCategory,
  ViewLocationValues,
  ViewPersistence,
  ViewRegistration,
};
