import { ContainerConfig, Container } from './Container';
import { UIInstanceManager } from '../UIManager';
import { UIUtils } from '../utils/UIUtils';
import { Spacer } from './Spacer';
import { PlayerAPI } from 'bitmovin-player';
import { i18n } from '../localization/i18n';
import { BrowserUtils } from '../utils/BrowserUtils';
import { Component, ComponentConfig } from './Component';
import { SettingsPanel } from './settings/SettingsPanel';

/**
 * Configuration interface for the {@link ControlBar}.
 *
 * @category Configs
 */
export interface ControlBarConfig extends ContainerConfig {
  // nothing yet
}

/**
 * A container for main player control components, e.g. play toggle button, seek bar, volume control, fullscreen toggle
 * button.
 *
 * @category Components
 */
export class ControlBar extends Container<ControlBarConfig> {
  constructor(config: ControlBarConfig) {
    super(config);

    this.config = this.mergeConfig(
      config,
      {
        cssClass: 'ui-controlbar',
        hidden: true,
        role: 'region',
        ariaLabel: i18n.getLocalizer('controlBar'),
      },
      <ControlBarConfig>this.config,
    );
  }

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

    // Counts how many components are hovered and block hiding of the control bar
    let hoverStackCount = 0;
    let isSettingsPanelShown = false;

    // Only enabling this for platforms without touch input.
    // Enabling this for touch devices causes the UI to not disappear after hideDelay seconds,
    // because `mouseleave` event is not emitted.
    // Instead, it will stay visible until another manual interaction is performed.
    if (uimanager.getConfig().disableAutoHideWhenHovered && !BrowserUtils.isTouchSupported) {
      // Track hover status of child components
      UIUtils.traverseTree(this, component => {
        // Do not track hover status of child containers or spacers, only of 'real' controls
        if (component instanceof Container || component instanceof Spacer) {
          return;
        }

        // Subscribe hover event and keep a count of the number of hovered children
        component.onHoverChanged.subscribe((_, args) => {
          if (args.hovered) {
            hoverStackCount++;
          } else {
            hoverStackCount--;
          }
        });
      });
    }

    if (BrowserUtils.isMobile) {
      uimanager.onComponentShow.subscribe((component: Component<ComponentConfig>) => {
        if (component instanceof SettingsPanel) {
          isSettingsPanelShown = true;
        }
      });

      uimanager.onComponentHide.subscribe((component: Component<ComponentConfig>) => {
        if (component instanceof SettingsPanel) {
          isSettingsPanelShown = false;
        }
      });
    }

    uimanager.onControlsShow.subscribe(() => {
      this.show();
    });

    uimanager.onPreviewControlsHide.subscribe((sender, args) => {
      // Cancel the hide event if hovered child components block hiding or if the settings panel is active on mobile.
      args.cancel = args.cancel || hoverStackCount > 0 || isSettingsPanelShown;
    });

    uimanager.onControlsHide.subscribe(() => {
      this.hide();
    });
  }
}
