import '../../../assert/js/assert.js';
import '../../../globals.js';
// Copyright 2021-2024, University of Colorado Boulder
/**
 * Dialog with preferences to enable or disable various features for the simulation. Groups of preferences are
 * organized and displayed in a tab panel.
 *
 * Once the dialog is created it is never destroyed so listeners and components do not need to be disposed.
 *
 * @author Jesse Greenberg (PhET Interactive Simulations)
 */
import DerivedProperty from '../../../axon/js/DerivedProperty.js';
import EnumerationProperty from '../../../axon/js/EnumerationProperty.js';
import optionize from '../../../phet-core/js/optionize.js';
import PhetFont from '../../../scenery-phet/js/PhetFont.js';
import { FocusManager, HSeparator, KeyboardListener, Text, VBox } from '../../../scenery/js/imports.js';
import Dialog from '../../../sun/js/Dialog.js';
import soundManager from '../../../tambo/js/soundManager.js';
import joist from '../joist.js';
import JoistStrings from '../JoistStrings.js';
import PreferencesPanels from './PreferencesPanels.js';
import PreferencesTabs from './PreferencesTabs.js';
import PreferencesTabSwitchSoundGenerator from './PreferencesTabSwitchSoundGenerator.js';
import PreferencesType from './PreferencesType.js';
// constants
const TITLE_FONT = new PhetFont({ size: 24, weight: 'bold' });
const TAB_FONT = new PhetFont(20);
const TAB_MAX_WIDTH = 120;
const TAB_OPTIONS = {
    font: TAB_FONT,
    maxWidth: TAB_MAX_WIDTH
};
const CONTENT_FONT = new PhetFont(16);
const CONTENT_MAX_WIDTH = 500;
const PANEL_SECTION_CONTENT_OPTIONS = {
    font: CONTENT_FONT,
    maxWidth: CONTENT_MAX_WIDTH
};
const PANEL_SECTION_LABEL_FONT = new PhetFont({ weight: 'bold', size: 16 });
const PANEL_SECTION_LABEL_MAX_WIDTH = 360;
const PANEL_SECTION_LABEL_OPTIONS = {
    font: PANEL_SECTION_LABEL_FONT,
    maxWidth: PANEL_SECTION_LABEL_MAX_WIDTH
};
class PreferencesDialog extends Dialog {
    constructor(preferencesModel, providedOptions) {
        const titleText = new Text(JoistStrings.preferences.titleStringProperty, {
            font: TITLE_FONT,
            maxWidth: CONTENT_MAX_WIDTH // The width of the title should be the same max as for a panel section
        });
        const options = optionize()({
            titleAlign: 'center',
            title: titleText,
            isDisposable: false,
            // phet-io
            phetioDynamicElement: true,
            closeButtonVoicingDialogTitle: JoistStrings.preferences.titleStringProperty
        }, providedOptions);
        // determine which tabs will be supported in this Dialog, true if any entry in a configuration has content
        const supportedTabs = [PreferencesType.OVERVIEW]; // There is always an "Overview" tab
        preferencesModel.supportsSimulationPreferences() && supportedTabs.push(PreferencesType.SIMULATION);
        preferencesModel.supportsVisualPreferences() && supportedTabs.push(PreferencesType.VISUAL);
        preferencesModel.supportsAudioPreferences() && supportedTabs.push(PreferencesType.AUDIO);
        preferencesModel.supportsInputPreferences() && supportedTabs.push(PreferencesType.INPUT);
        preferencesModel.supportsLocalizationPreferences() && supportedTabs.push(PreferencesType.LOCALIZATION);
        assert && assert(supportedTabs.length > 0, 'Trying to create a PreferencesDialog with no tabs, check PreferencesModel');
        // the selected PreferencesType, indicating which tab is visible in the Dialog
        const selectedTabProperty = new EnumerationProperty(PreferencesType.OVERVIEW, {
            validValues: supportedTabs,
            tandem: options.tandem.createTandem('selectedTabProperty')
        });
        // the set of tabs you can click to activate a tab panel
        const preferencesTabs = new PreferencesTabs(supportedTabs, selectedTabProperty, {
            tandem: options.tandem.createTandem('preferencesTabs')
        });
        // the panels of content with UI components to select preferences, only one is displayed at a time
        const preferencesPanels = new PreferencesPanels(preferencesModel, supportedTabs, selectedTabProperty, preferencesTabs, {
            tandem: options.tandem.createTandem('preferencesPanels')
        });
        // visual separator between tabs and panels - as long as the widest separated content, which may change with i18n
        const content = new VBox({
            children: [
                preferencesTabs,
                new HSeparator({
                    layoutOptions: {
                        bottomMargin: 20,
                        stretch: true
                    }
                }),
                preferencesPanels
            ]
        });
        // sound generation for tab switching
        const tabSwitchSoundGenerator = new PreferencesTabSwitchSoundGenerator(selectedTabProperty, {
            initialOutputLevel: 0.2
        });
        soundManager.addSoundGenerator(tabSwitchSoundGenerator, {
            categoryName: 'user-interface'
        });
        super(content, options);
        this.preferencesTabs = preferencesTabs;
        this.preferencesPanels = preferencesPanels;
        // pdom - When the "down" arrow is pressed on the group of tabs, move focus to the selected panel
        preferencesTabs.addInputListener(new KeyboardListener({
            keys: ['arrowDown'],
            fire: () => {
                this.focusSelectedPanel();
            }
        }));
        content.addInputListener(new KeyboardListener({
            keys: ['arrowUp'],
            fire: event => {
                this.focusSelectedTab();
            },
            // This listener is only enabled when the focus is on the panel itself, not its children. Panel contents
            // will often use arrow keys themselves, so this prevents an overlap.
            enabledProperty: new DerivedProperty([FocusManager.pdomFocusProperty], () => {
                const pdomFocusedNode = FocusManager.getPDOMFocusedNode();
                return !!pdomFocusedNode && this.preferencesPanels.isFocusableSelectedContent(pdomFocusedNode);
            })
        }));
    }
    /**
     * Move focus to the selected tab. Generally to be used when opening the dialog.
     */
    focusSelectedTab() {
        this.preferencesTabs.focusSelectedTab();
    }
    /**
     * Move focus to the selected panel.
     */
    focusSelectedPanel() {
        this.preferencesPanels.focusSelectedPanel();
    }
}
// Font and options for the text that labels a tab in the dialog.
PreferencesDialog.TAB_FONT = TAB_FONT;
PreferencesDialog.TAB_OPTIONS = TAB_OPTIONS;
// The font for a title of a panel in the dialog.
PreferencesDialog.TITLE_FONT = TITLE_FONT;
// The font, max width, and options for most text content in the dialog.
PreferencesDialog.CONTENT_FONT = CONTENT_FONT;
PreferencesDialog.CONTENT_MAX_WIDTH = CONTENT_MAX_WIDTH;
PreferencesDialog.PANEL_SECTION_CONTENT_OPTIONS = PANEL_SECTION_CONTENT_OPTIONS;
// The font, max width, and options for a label for a section of content in the dialog.
PreferencesDialog.PANEL_SECTION_LABEL_FONT = PANEL_SECTION_LABEL_FONT;
PreferencesDialog.PANEL_SECTION_LABEL_MAX_WIDTH = PANEL_SECTION_LABEL_MAX_WIDTH;
PreferencesDialog.PANEL_SECTION_LABEL_OPTIONS = PANEL_SECTION_LABEL_OPTIONS;
// Default spacing between unique items in a preferences dialog
PreferencesDialog.CONTENT_SPACING = 20;
// Default vertical spacing between grouped items (radio buttons, vertical checkboxes, ...)
PreferencesDialog.VERTICAL_CONTENT_SPACING = 5;
// Content or UI component intendentation under a PreferencesPanelSection title.
PreferencesDialog.CONTENT_INDENTATION_SPACING = 15;
// Default vertical spacing between a label and its collection of contents for a control in the dialog.
PreferencesDialog.LABEL_CONTENT_SPACING = 10;
joist.register('PreferencesDialog', PreferencesDialog);
export default PreferencesDialog;
//# sourceMappingURL=PreferencesDialog.js.map