// Type definitions for sandstone/VideoPlayer

import { SlottableProps as ui_Slottable_SlottableProps } from "@enact/ui/Slottable";
import * as React from "react";

type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>;
type Merge<M, N> = Omit<M, Extract<keyof M, keyof N>> & N;

export interface VideoProps extends ui_Slottable_SlottableProps {
  /**
   * Video plays automatically.
   */
  autoPlay?: boolean;
  /**
 * Video component to use.
 * 
 * The default ( `'video'` ) renders an  `HTMLVideoElement` . Custom video components must have
a similar API structure, exposing the following APIs:
 * 
 * Properties:
 * *  `currentTime`  {Number} - Playback index of the media in seconds
 * *  `duration`  {Number} - Media's entire duration in seconds
 * *  `error`  {Boolean} -  `true`  if video playback has errored.
 * *  `loading`  {Boolean} -  `true`  if video playback is loading.
 * *  `paused`  {Boolean} - Playing vs paused state.  `true`  means the media is paused
 * *  `playbackRate`  {Number} - Current playback rate, as a number
 * *  `proportionLoaded`  {Number} - A value between  `0`  and  `1` 
representing the proportion of the media that has loaded
 * *  `proportionPlayed`  {Number} - A value between  `0`  and  `1`  representing the
proportion of the media that has already been shown
 * 
 * Events:
 * *  `onLoadStart`  - Called when the video starts to load
 * *  `onPlay`  - Sent when playback of the media starts after having been paused
 * *  `onUpdate`  - Sent when any of the properties were updated
 * 
 * Methods:
 * *  `play()`  - play video
 * *  `pause()`  - pause video
 * *  `load()`  - load video
 * 
 * The    property is passed to
the video component as a child node.
 */
  mediaComponent?: string | React.ComponentType | JSX.Element;
  /**
   * The video source to be preloaded. Expects a  `<source>`  node.
   */
  preloadSource?: React.ReactNode;
  /**
 * The video source to be played.
 * 
 * Any children  `<source>`  elements will be sent directly to the  `mediaComponent`  as video
sources.
 * 
 * See:  
 */
  source?: string | React.ReactNode;
}
/**
 * Provides support for more advanced video configurations for  `VideoPlayer` .
 * 
 * Custom Video Tag
 * ```
<VideoPlayer>
  <Video mediaComponent="custom-video-element">
    <source src="path/to/source.mp4" />
  </Video>
</VideoPlayer>
```
 
 * Preload Video Source
 * ```
<VideoPlayer>
  <Video>
    <source src="path/to/source.mp4" />
    <source src="path/to/preload-source.mp4" slot="preloadSource" />
  </Video>
</VideoPlayer>
```
 */

export class Video extends React.Component<
  Merge<React.HTMLProps<HTMLElement>, VideoProps>
> {}

/**
 * Every callback sent by    receives a status package,
which includes an object with the following key/value pairs as the first argument:
 */
export interface videoStatus {
  /**
   * Type of event that triggered this callback
   */
  type: string /**
   * Playback index of the media in seconds
   */;
  currentTime: number /**
   * Media's entire duration in seconds
   */;
  duration: number /**
   * Playing vs paused state.  `true`  means the media is paused
   */;
  paused: boolean /**
   * Current playback rate, as a number
   */;
  playbackRate: number /**
   * A value between  `0`  and  `1`  representing the proportion of the media that has loaded
   */;
  proportionLoaded: number /**
   * A value between  `0`  and  `1`  representing the proportion of the media that has already been shown
   */;
  proportionPlayed: number;
}
/**
 * A set of playback rates when media fast forwards, rewinds, slow-forwards, or slow-rewinds.
 * 
 * The number used for each operation is proportional to the normal playing speed, 1. If the rate
is less than 1, it will play slower than normal speed, and, if it is larger than 1, it will play
faster. If it is negative, it will play backward.
 * 
 * The order of numbers represents the incremental order of rates that will be used for each
operation. Note that rates can be expressed as decimals, strings, and fractions.
(e.g.:  `0.5` ,  `'0.5'` ,  `'1/2'` ).
 */
export interface playbackRateHash {
  /**
   * An array of playback rates when media fast forwards
   */
  fastForward: Array /**
   * An array of playback rates when media rewinds
   */;
  rewind: Array /**
   * An array of playback rates when media slow-forwards
   */;
  slowForward: Array /**
   * An array of playback rates when media slow-rewinds
   */;
  slowRewind: Array;
}
export interface VideoPlayerBaseProps {
  /**
   * The time (in milliseconds) before the control buttons will hide.
   *
   * Setting this to 0 or  `null`  disables closing, requiring user input to open and close.
   */
  autoCloseTimeout?: number;
  /**
   * Sets the hint string read when focusing the back button.
   */
  backButtonAriaLabel?: string;
  /**
 * Removes interactive capability from this component. This includes, but is not limited to,
key-press events, most clickable buttons, and prevents the showing of the controls.
 */
  disabled?: boolean;
  /**
 * Amount of time (in milliseconds) after which the feedback text/icon part of the slider's
tooltip will automatically hidden after the last action.
Setting this to 0 or  `null`  disables feedbackHideDelay; feedback will always be present.
 */
  feedbackHideDelay?: number;
  /**
 * Components placed below the title.
 * 
 * Typically these will be media descriptor icons, like how many audio channels, what codec
the video uses, but can also be a description for the video or anything else that seems
appropriate to provide information about the video to the user.
 */
  infoComponents?: React.ReactNode;
  /**
 * The number of milliseconds that the player will pause before firing the
first jump event on a right or left pulse.
 */
  initialJumpDelay?: number;
  /**
 * The number of seconds the player should skip forward or backward when a "jump" button is
pressed.
 */
  jumpBy?: number;
  /**
 * The number of milliseconds that the player will throttle before firing a
jump event on a right or left pulse.
 */
  jumpDelay?: number;
  /**
 * Manually set the loading state of the media, in case you have information that
 `VideoPlayer`  does not have.
 */
  loading?: boolean;
  /**
 * The current locale as a
  .
 */
  locale?: string;
  /**
   * Overrides the default media control component to support customized behaviors.
   *
   * The provided component will receive the following props from  `VideoPlayer` :
   * *  `initialJumpDelay`  - Time (in ms) to wait before starting a jump
   * *  `jumpDelay`  -  - Time (in ms) to wait between jumps
   * *  `mediaDisabled`  -  `true`  when the media controls are not interactive
   * *  `no5WayJump`  -  `true`  when 5-way jumping is disabled
   * *  `onClose`  - Called when cancel key is pressed when the media controls are visible
   * *  `onFastForward`  - Called when the media is fast forwarded via a key event
   * *  `onJump`  - Called when the media jumps either forward or backward
   * *  `onJumpBackwardButtonClick`  - Called when the jump backward button is pressed
   * *  `onJumpForwardButtonClick`  - Called when the jump forward button is pressed
   * *  `onKeyDown`  - Called when a key is pressed
   * *  `onPause`  - Called when the media is paused via a key event
   * *  `onPlay`  - Called when the media is played via a key event
   * *  `onRewind`  - Called when the media is rewound via a key event
   * *  `onToggleMore`  - Called when the more components are hidden or shown
   * *  `paused`  -  `true`  when the media is paused
   * *  `spotlightId`  - The spotlight container Id for the media controls
   * *  `spotlightDisabled`  -  `true`  when spotlight is disabled for the media controls
   * *  `visible`  -  `true`  when the media controls should be displayed
   */
  mediaControlsComponent?: React.ComponentType | JSX.Element;
  /**
 * Amount of time (in milliseconds), after the last user action, that the  `miniFeedback` 
will automatically hide.
Setting this to 0 or  `null`  disables  `miniFeedbackHideDelay` ;  `miniFeedback`  will always
be present.
 */
  miniFeedbackHideDelay?: number;
  /**
 * Disable audio for this video.
 * 
 * In a TV context, this is handled by the remote control, not programmatically in the
VideoPlayer API.
 */
  muted?: boolean;
  /**
   * Prevents the default behavior of using left and right keys for seeking.
   */
  no5WayJump?: boolean;
  /**
   * Prevents the default behavior of playing a video immediately after it's loaded.
   */
  noAutoPlay?: boolean;
  /**
   * Prevents the default behavior of showing media controls immediately after it's loaded.
   */
  noAutoShowMediaControls?: boolean;
  /**
   * Hides media slider feedback when fast forward or rewind while media controls are hidden.
   */
  noMediaSliderFeedback?: boolean;
  /**
   * Removes the mini feedback.
   */
  noMiniFeedback?: boolean;
  /**
   * Removes the media slider.
   */
  noSlider?: boolean;
  /**
   * Removes spinner while loading.
   */
  noSpinner?: boolean;
  /**
   * Called when the back button is clicked.
   */
  onBack?: Function;
  /**
 * Called when the player's controls change availability, whether they are shown
or hidden.
 * 
 * The current status is sent as the first argument in an object with a key  `available` 
which will be either  `true`  or  `false` . (e.g.:  `onControlsAvailable({available: true})` )
 */
  onControlsAvailable?: Function;
  /**
   * Called when the video has been fast forwarded.
   */
  onFastForward?: Function;
  /**
   * Called when the user clicks the JumpBackward button.
   *
   * Is passed a    as the first argument.
   */
  onJumpBackward?: Function;
  /**
   * Called when the user clicks the JumpForward button.
   *
   * Is passed a    as the first argument.
   */
  onJumpForward?: Function;
  /**
   * Called when the video has been paused.
   */
  onPause?: Function;
  /**
   * Called when the video has been played.
   */
  onPlay?: Function;
  /**
   * Called when the video has been rewound.
   */
  onRewind?: Function;
  /**
 * Called when the user is moving the VideoPlayer's Slider knob independently of
the current playback position.
 * 
 * It is passed an object with a  `seconds`  key (float value) to indicate the current time
index. It can be used to update the  `thumbnailSrc`  to the reflect the current scrub
position.
 */
  onScrub?: Function;
  /**
   * Called when seek is attempted while  `seekDisabled`  is true.
   */
  onSeekFailed?: Function;
  /**
 * Called when seeking outside of the current  `selection`  range.
 * 
 * By default, the seek will still be performed. Calling  `preventDefault()`  on the event
will prevent the seek operation.
 */
  onSeekOutsideSelection?: Function;
  /**
 * Called when the visibility of more components is changed
 * 
 * Event payload includes:
 * *  `type`  - Type of event,  `'onToggleMore'`
 * *  `showMoreComponents`  -  `true`  when the components are visible`
 * *  `liftDistance`  - The distance, in pixels, the component animates
`
 */
  onToggleMore?: Function;
  /**
   * Called once before the video is forwarded.
   */
  onWillFastForward?: Function;
  /**
   * Called once before the video is jump backwarded.
   *
   * Is passed a    as the first argument.
   */
  onWillJumpBackward?: Function;
  /**
   * Called once before the video is jump forwarded.
   *
   * Is passed a    as the first argument.
   */
  onWillJumpForward?: Function;
  /**
   * Called once before the video is paused.
   */
  onWillPause?: Function;
  /**
   * Called once before the video is played
   */
  onWillPlay?: Function;
  /**
   * Called once before the video is rewound.
   */
  onWillRewind?: Function;
  /**
 * Pauses the video when it reaches either the start or the end of the video during rewind,
slow rewind, fast forward, or slow forward.
 */
  pauseAtEnd?: boolean;
  /**
   * Mapping of playback rate names to playback rate values that may be set.
   */
  playbackRateHash?: playbackRateHash;
  /**
   * Disables seek function.
   *
   * Note that jump by arrow keys will also be disabled when  `true` .
   */
  seekDisabled?: boolean;
  /**
 * A range of the video to display as selected.
 * 
 * The value of  `selection`  may either be:
 * *  `null`  or  `undefined`  for no selection,
 * *  a single-element array with the start time of the selection
 * *  a two-element array containing both the start and end time of the selection in seconds
 * 
 * When the start time is specified, the media slider will show filled starting at that
time to the current time.
 * 
 * When the end time is specified, the slider's background will be filled between the two
times.
 */
  selection?: number[];
  /**
 * The video source.
 * 
 * Any children  `<source>`  tag elements of    will
be sent directly to the  `videoComponent`  as video sources.
 */
  source?: React.ReactNode;
  /**
   * Disables spotlight navigation into the component.
   */
  spotlightDisabled?: boolean;
  /**
   * The spotlight container ID for the player.
   */
  spotlightId?: string;
  /**
 * The thumbnail component to be used instead of the built-in version.
 * 
 * The internal thumbnail style will not be applied to this component. This component
follows the same rules as the built-in version.
 */
  thumbnailComponent?: string | React.ComponentType | JSX.Element;
  /**
 * Thumbnail image source to show on the slider knob.
 * 
 * This is a standard    component so it supports all of the same
options for the  `src`  property. If no  `thumbnailComponent`  and no  `thumbnailSrc`  is set,
no tooltip will display.
 */
  thumbnailSrc?: string | object;
  /**
   * Enables the thumbnail transition from opaque to translucent.
   */
  thumbnailUnavailable?: boolean;
  /**
   * Title for the video being played.
   */
  title?: string | React.ReactNode;
  /**
   * The time (in milliseconds) before the title disappears from the controls.
   *
   * Setting this to  `0`  disables hiding.
   */
  titleHideDelay?: number;
  /**
 * Video component to use.
 * 
 * The default renders an  `HTMLVideoElement` . Custom video components must have a similar
API structure, exposing the following APIs:
 * 
 * Properties:
 * *  `currentTime`  {Number} - Playback index of the media in seconds
 * *  `duration`  {Number} - Media's entire duration in seconds
 * *  `error`  {Boolean} -  `true`  if video playback has errored.
 * *  `loading`  {Boolean} -  `true`  if video playback is loading.
 * *  `paused`  {Boolean} - Playing vs paused state.  `true`  means the media is paused
 * *  `playbackRate`  {Number} - Current playback rate, as a number
 * *  `proportionLoaded`  {Number} - A value between  `0`  and  `1` 
representing the proportion of the media that has loaded
 * *  `proportionPlayed`  {Number} - A value between  `0`  and  `1`  representing the
proportion of the media that has already been shown
 * 
 * Events:
 * *  `onLoadStart`  - Called when the video starts to load
 * *  `onUpdate`  - Sent when any of the properties were updated
 * 
 * Methods:
 * *  `play()`  - play video
 * *  `pause()`  - pause video
 * *  `load()`  - load video
 * 
 * The    property is passed to
the video component as a child node.
 */
  videoComponent?: React.ComponentType | JSX.Element;
}
/**
 * A player for video   .
 */

export class VideoPlayerBase extends React.Component<
  Merge<React.HTMLProps<HTMLElement>, VideoPlayerBaseProps>
> {
  /**
   * Shows media controls.
   */
  showControls(): void;
  /**
   * Hides media controls.
   */
  hideControls(): void;
  /**
   * Toggles the media controls.
   */
  toggleControls(): void;
  /**
 * Returns an object with the current state of the media including  `currentTime` ,  `duration` ,
 `paused` ,  `playbackRate` ,  `proportionLoaded` , and  `proportionPlayed` .
 */
  getMediaState(): object;
  /**
 * Programmatically plays the current media.
If you call this function during fast forwarding or rewinding, the playback speed will be set to normal.
 */
  play(): void;
  /**
 * Programmatically pauses the current media.
If you call this function during fast forwarding or rewinding, the playback speed will be set to normal.
 */
  pause(): void;
  /**
   * Sets the media playback time index.
   */
  seek(timeIndex: number): void;
  /**
 * Step a given amount of time away from the current playback position.
Like    but relative.
 */
  jump(distance: number): void;
  /**
 * Fast forwards the current media for seeking.
This function changes the playback rate.
If you call  `play`  or  `pause`  during fast forwarding, the playback speed will be set to normal.
 */
  fastForward(): void;
  /**
 * Rewinds the current media for seeking.
This function changes the playback rate.
If you call  `play`  or  `pause`  during rewinding, the playback speed will be set to normal.
 */
  rewind(): void;
  /**
   * Sets the playback speed.
   */
  setPlaybackSpeed(rate: number): boolean;
  /**
   * Returns a proxy to the underlying  `<video>`  node currently used by the VideoPlayer
   */
  getVideoNode(): void;
}

export interface VideoPlayerProps extends ui_Slottable_SlottableProps {}
/**
 * A standard HTML5 video player for Sandstone. It behaves, responds to, and operates like a
 `<video>`  tag in its support for  `<source>` .  It also accepts custom tags such as
 `<infoComponents>`  for displaying additional information in the title area and  `<MediaControls>` 
for handling media playback controls and adding more controls.
 * 
 * Example usage:
 * ```
<VideoPlayer title="Hilarious Cat Video" poster="http://my.cat.videos/boots-poster.jpg">
	<source src="http://my.cat.videos/boots.mp4" type="video/mp4" />
	<infoComponents>A video about my cat Boots, wearing boots.</infoComponents>
	<MediaControls>
		<leftComponents><Button backgroundOpacity="translucent" icon="star" /></leftComponents>
		<rightComponents><Button backgroundOpacity="translucent" icon="notification" /></rightComponents>

		<Button backgroundOpacity="translucent">Add To Favorites</Button>
		<Button backgroundOpacity="translucent" icon="search" />
	</MediaControls>
</VideoPlayer>
```
 
 * To invoke methods (e.g.:  `fastForward()` ) or get the current state ( `getMediaState()` ), store a
ref to the  `VideoPlayer`  within your component:
 * ```
	...

	setVideoPlayer = (node) => {
		this.videoPlayer = node;
	}

	play () {
		this.videoPlayer.play();
	}

	render () {
		return (
			<VideoPlayer ref={this.setVideoPlayer} />
		);
	}
```
 */

export class VideoPlayer extends React.Component<
  Merge<React.HTMLProps<HTMLElement>, VideoPlayerProps>
> {}

export default VideoPlayer;
