// Copyright 2017-2025, University of Colorado Boulder

/**
 * TextKeyNode is a KeyNode with a text icon. It has layout, spacing, and defaults for KeyNode that are suited for text.
 *
 * @author Jesse Greenberg
 */

import { string_scenery_phet_key_option_StringProperty } from '../strings/key/option.js';
import { string_scenery_phet_key_alt_StringProperty } from '../strings/key/alt.js';
import { string_scenery_phet_key_capsLock_StringProperty } from '../strings/key/capsLock.js';
import { string_scenery_phet_key_esc_StringProperty } from '../strings/key/esc.js';
import { string_scenery_phet_key_end_StringProperty } from '../strings/key/end.js';
import { string_scenery_phet_key_enter_StringProperty } from '../strings/key/enter.js';
import { string_scenery_phet_key_fn_StringProperty } from '../strings/key/fn.js';
import { string_scenery_phet_key_home_StringProperty } from '../strings/key/home.js';
import { string_scenery_phet_key_pageDown_StringProperty } from '../strings/key/pageDown.js';
import { string_scenery_phet_key_pageUp_StringProperty } from '../strings/key/pageUp.js';
import { string_scenery_phet_key_space_StringProperty } from '../strings/key/space.js';
import { string_scenery_phet_key_shift_StringProperty } from '../strings/key/shift.js';
import { string_scenery_phet_key_tab_StringProperty } from '../strings/key/tab.js';
import '../../../globals.js';
import PhetioProperty from '../../../axon/js/PhetioProperty.js';
import TReadOnlyProperty from '../../../axon/js/TReadOnlyProperty.js';
import optionize from '../../../phet-core/js/optionize.js';
import platform from '../../../phet-core/js/platform.js';
import RichText from '../../../scenery/js/nodes/RichText.js';
import Font from '../../../scenery/js/util/Font.js';
import TColor from '../../../scenery/js/util/TColor.js';
import PhetFont from '../PhetFont.js';
import sceneryPhet from '../sceneryPhet.js';
import KeyNode, { KeyNodeOptions } from './KeyNode.js';

type SelfOptions = {
  font?: Font;
  fill?: TColor;
  textMaxWidth?: number;
};

export type TextKeyNodeOptions = SelfOptions & KeyNodeOptions;

export default class TextKeyNode extends KeyNode {

  public constructor( string: string | TReadOnlyProperty<string>, providedOptions?: TextKeyNodeOptions ) {

    // margins, width, and height in ScreenView coordinates
    const options = optionize<TextKeyNodeOptions, SelfOptions, KeyNodeOptions>()( {

      // text options
      font: new PhetFont( { size: 16 } ),
      fill: 'black',
      textMaxWidth: 55, // Long keys like Space, Enter, Tab, Shift are all smaller than this.

      // by default, key should tightly surround the text, with a bit more horizontal space
      xPadding: 11
    }, providedOptions );

    // use RichText because some keys (like page up/page down/caps lock) might span multiple lines
    const text = new RichText( string, {
      font: options.font,
      fill: options.fill,
      maxWidth: options.textMaxWidth
    } );

    super( text, options );
    this.addDisposable( text );
  }

  /**
   * Returns the correct platform dependent key string for "Alt". "Alt" on Windows, "Option" on Mac.
   */
  public static getAltKeyString(): PhetioProperty<string> {
    return platform.mac ?
           string_scenery_phet_key_option_StringProperty :
           string_scenery_phet_key_alt_StringProperty;
  }

  //-------------------------------------------------------------------------------------------------
  // Static factory methods for specific text strings. For brevity, these methods have the same names
  // as their string keys. For example string_scenery_phet_key_esc_StringProperty is rendered by the esc method.
  //-------------------------------------------------------------------------------------------------

  // Note that this will render "Alt" OR "Options", depending on platform. If there is a description of this icon
  // in the PDOM please use getAltKeyString().
  public static altOrOption( providedOptions?: KeyNodeOptions ): KeyNode {
    return new TextKeyNode( TextKeyNode.getAltKeyString(), providedOptions );
  }

  public static capsLock( providedOptions?: KeyNodeOptions ): KeyNode {
    return new TextKeyNode( string_scenery_phet_key_capsLock_StringProperty, providedOptions );
  }

  public static esc( providedOptions?: KeyNodeOptions ): KeyNode {
    return new TextKeyNode( string_scenery_phet_key_esc_StringProperty, providedOptions );
  }

  public static end( providedOptions?: KeyNodeOptions ): KeyNode {
    return new TextKeyNode( string_scenery_phet_key_end_StringProperty, providedOptions );
  }

  public static enter( providedOptions?: KeyNodeOptions ): KeyNode {
    return new TextKeyNode( string_scenery_phet_key_enter_StringProperty, providedOptions );
  }

  public static fn( providedOptions?: KeyNodeOptions ): KeyNode {
    return new TextKeyNode( string_scenery_phet_key_fn_StringProperty, providedOptions );
  }

  public static home( providedOptions?: KeyNodeOptions ): KeyNode {
    return new TextKeyNode( string_scenery_phet_key_home_StringProperty, providedOptions );
  }

  public static pageDown( providedOptions?: KeyNodeOptions ): KeyNode {
    return new TextKeyNode( string_scenery_phet_key_pageDown_StringProperty, providedOptions );
  }

  public static pageUp( providedOptions?: KeyNodeOptions ): KeyNode {
    return new TextKeyNode( string_scenery_phet_key_pageUp_StringProperty, providedOptions );
  }

  public static space( providedOptions?: KeyNodeOptions ): KeyNode {
    return new TextKeyNode( string_scenery_phet_key_space_StringProperty, providedOptions );
  }

  public static shift( providedOptions?: KeyNodeOptions ): KeyNode {
    return new TextKeyNode( string_scenery_phet_key_shift_StringProperty, providedOptions );
  }

  public static tab( providedOptions?: KeyNodeOptions ): KeyNode {
    return new TextKeyNode( string_scenery_phet_key_tab_StringProperty, providedOptions );
  }
}

sceneryPhet.register( 'TextKeyNode', TextKeyNode );