import { SelectBox } from './SelectBox';
import { ListSelectorConfig } from '../lists/ListSelector';
import { UIInstanceManager } from '../../UIManager';
import { PlayerAPI } from 'bitmovin-player';
import { i18n } from '../../localization/i18n';

/**
 * A select box providing a selection between 'auto' and the available audio qualities.
 *
 * @category Components
 */
export class AudioQualitySelectBox extends SelectBox {
  constructor(config: ListSelectorConfig = {}) {
    super(config);

    this.config = this.mergeConfig(
      config,
      {
        cssClasses: ['ui-audioqualityselectbox'],
      },
      this.config,
    );
  }

  configure(player: PlayerAPI, uimanager: UIInstanceManager): void {
    super.configure(player, uimanager);

    const selectCurrentAudioQuality = () => {
      this.selectItem(player.getAudioQuality().id);
    };

    const updateAudioQualities = () => {
      const audioQualities = player.getAvailableAudioQualities();

      this.clearItems();

      // Add entry for automatic quality switching (default setting)
      this.addItem('auto', i18n.getLocalizer('auto'));

      // Add audio qualities
      for (const audioQuality of audioQualities) {
        this.addItem(audioQuality.id, audioQuality.label);
      }

      // Select initial quality
      selectCurrentAudioQuality();
    };

    this.onItemSelectionChanged.subscribe((sender: AudioQualitySelectBox, value: string) => {
      player.setAudioQuality(value);
    });

    // Update qualities when audio track has changed
    player.on(player.exports.PlayerEvent.AudioChanged, updateAudioQualities);
    // Update qualities when source goes away
    player.on(player.exports.PlayerEvent.SourceUnloaded, updateAudioQualities);
    // Update qualities when the period within a source changes
    player.on(player.exports.PlayerEvent.PeriodSwitched, updateAudioQualities);
    // Update quality selection when quality is changed (from outside)
    player.on(player.exports.PlayerEvent.AudioQualityChanged, selectCurrentAudioQuality);
    if ((player.exports.PlayerEvent as any).AudioQualityAdded) {
      // Update qualities when their availability changed
      // TODO: remove any cast after next player release
      player.on((player.exports.PlayerEvent as any).AudioQualityAdded, updateAudioQualities);
      player.on((player.exports.PlayerEvent as any).AudioQualityRemoved, updateAudioQualities);
    }

    uimanager.getConfig().events.onUpdated.subscribe(updateAudioQualities);
  }
}
