import {initLogConstructor} from '#utils/log';

import {AmpStoryEntryPoint} from './amp-story-entry-point/amp-story-entry-point-impl';
import {AmpStoryPlayer} from './amp-story-player-impl';
import {AmpStoryPlayerViewportObserver} from './amp-story-player-viewport-observer';

export class AmpStoryComponentManager {
  /**
   * @param {!Window} win
   * @constructor
   */
  constructor(win) {
    /** @private {!Window} */
    this.win_ = win;
  }

  /**
   * Calls layoutPlayer on the element when it is close to the viewport.
   * @param {!Element} element
   * @private
   */
  layoutEl_(element) {
    new AmpStoryPlayerViewportObserver(this.win_, element, () =>
      element.layoutPlayer()
    );

    const scrollHandler = () => {
      element.layoutPlayer();
      this.win_.removeEventListener('scroll', scrollHandler);
    };

    this.win_.addEventListener('scroll', scrollHandler);
  }

  /**
   * Builds and layouts the players when appropriate.
   * @public
   */
  loadPlayers() {
    const doc = this.win_.document;
    const players = doc.getElementsByTagName('amp-story-player');
    initLogConstructor();
    for (let i = 0; i < players.length; i++) {
      const playerEl = players[i];
      const player = new AmpStoryPlayer(this.win_, playerEl);
      player.buildPlayer();
      this.layoutEl_(player);
    }
  }

  /**
   * Builds and layouts entry points.
   * @public
   */
  loadEntryPoints() {
    const doc = this.win_.document;
    const entryPoints = doc.getElementsByTagName('amp-story-entry-point');
    initLogConstructor();

    for (let i = 0; i < entryPoints.length; i++) {
      const entryPointEl = entryPoints[i];
      const entryPoint = new AmpStoryEntryPoint(this.win_, entryPointEl);
      entryPoint.buildCallback();
      this.layoutEl_(entryPoint);
    }
  }
}
