text: var registerComponent = require('../../core/component').registerComponent;
  var constants = require('../../constants/');
  var utils = require('../../utils/');
  var bind = utils.bind;
  
  var ENTER_VR_CLASS = 'a-enter-vr';
  var ENTER_AR_CLASS = 'a-enter-ar';
  var ENTER_VR_BTN_CLASS = 'a-enter-vr-button';
  var ENTER_AR_BTN_CLASS = 'a-enter-ar-button';
  var HIDDEN_CLASS = 'a-hidden';
  var ORIENTATION_MODAL_CLASS = 'a-orientation-modal';
  
  /**
   * UI for entering VR mode.
   */
  module.exports.Component = registerComponent('vr-mode-ui', {
    dependencies: ['canvas'],
  
    schema: {
      enabled: {default: true},
      enterVRButton: {default: ''},
      enterARButton: {default: ''}
    },
  
    init: function () {
      var self = this;
      var sceneEl = this.el;
  
      if (utils.getUrlParameter('ui') === 'false') { return; }
  
      this.insideLoader = false;
      this.enterVREl = null;
      this.enterAREl = null;
      this.orientationModalEl = null;
      this.bindMethods();
  
      // Hide/show VR UI when entering/exiting VR mode.
      sceneEl.addEventListener('enter-vr', this.updateEnterInterfaces);
      sceneEl.addEventListener('exit-vr', this.updateEnterInterfaces);
      sceneEl.addEventListener('update-vr-devices', this.updateEnterInterfaces);
  
      window.addEventListener('message', function (event) {
        if (event.data.type === 'loaderReady') {
          self.insideLoader = true;
          self.remove();
        }
      });
  
      // Modal that tells the user to change orientation if in portrait.
      window.addEventListener('orientationchange', this.toggleOrientationModalIfNeeded);
    },
  
    bindMethods: function () {
      this.onEnterVRButtonClick = bind(this.onEnterVRButtonClick, this);
      this.onEnterARButtonClick = bind(this.onEnterARButtonClick, this);
      this.onModalClick = bind(this.onModalClick, this);
      this.toggleOrientationModalIfNeeded = bind(this.toggleOrientationModalIfNeeded, this);
      this.updateEnterInterfaces = bind(this.updateEnterInterfaces, this);
    },
  
    /**
     * Exit VR when modal clicked.
     */
    onModalClick: function () {
      this.el.exitVR();
    },
  
    /**
     * Enter VR when clicked.
     */
    onEnterVRButtonClick: function () {
      this.el.enterVR();
    },
  
    /**
     * Enter AR when clicked.
     */
    onEnterARButtonClick: function () {
      this.el.enterAR();
    },
  
    update: function () {
      var data = this.data;
      var sceneEl = this.el;
  
      if (!data.enabled || this.insideLoader || utils.getUrlParameter('ui') === 'false') {
        return this.remove();
      }
  
      if (this.enterVREl || this.enterAREl || this.orientationModalEl) { return; }
  
      // Add UI if enabled and not already present.
      if (data.enterVRButton) {
        // Custom button.
        this.enterVREl = document.querySelector(data.enterVRButton);
        this.enterVREl.addEventListener('click', this.onEnterVRButtonClick);
      } else {
        this.enterVREl = createEnterVRButton(this.onEnterVRButtonClick);
        sceneEl.appendChild(this.enterVREl);
      }
      if (data.enterARButton) {
        // Custom button.
        this.enterAREl = document.querySelector(data.enterARButton);
        this.enterAREl.addEventListener('click', this.onEnterARButtonClick);
      } else {
        this.enterAREl = createEnterARButton(this.onEnterARButtonClick);
        sceneEl.appendChild(this.enterAREl);
      }
  
      this.orientationModalEl = createOrientationModal(this.onModalClick);
      sceneEl.appendChild(this.orientationModalEl);
  
      this.updateEnterInterfaces();
    },
  
    remove: function () {
      [this.enterVREl, this.enterAREl, this.orientationModalEl].forEach(function (uiElement) {
        if (uiElement && uiElement.parentNode) {
          uiElement.parentNode.removeChild(uiElement);
        }
      });
    },
  
    updateEnterInterfaces: function () {
      this.toggleEnterVRButtonIfNeeded();
      this.toggleEnterARButtonIfNeeded();
      this.toggleOrientationModalIfNeeded();
    },
  
    toggleEnterVRButtonIfNeeded: function () {
      var sceneEl = this.el;
      if (!this.enterVREl) { return; }
      if (sceneEl.is('vr-mode')) {
        this.enterVREl.classList.add(HIDDEN_CLASS);
      } else {
        this.enterVREl.classList.remove(HIDDEN_CLASS);
      }
    },
  
    toggleEnterARButtonIfNeeded: function () {
      var sceneEl = this.el;
      if (!this.enterAREl) { return; }
      // Hide the button while in a session, or if AR is not supported.
      if (sceneEl.is('vr-mode') || !utils.device.checkARSupport()) {
        this.enterAREl.classList.add(HIDDEN_CLASS);
      } else {
        this.enterAREl.classList.remove(HIDDEN_CLASS);
      }
    },
  
    toggleOrientationModalIfNeeded: function () {
      var sceneEl = this.el;
      var orientationModalEl = this.orientationModalEl;
      if (!orientationModalEl || !sceneEl.isMobile) { return; }
      if (!utils.device.isLandscape() && sceneEl.is('vr-mode')) {
        // Show if in VR mode on portrait.
        orientationModalEl.classList.remove(HIDDEN_CLASS);
      } else {
        orientationModalEl.classList.add(HIDDEN_CLASS);
      }
    }
  });
  
  /**
   * Create a button that when clicked will enter into stereo-rendering mode for VR.
   *
   * Structure: <div><button></div>
   *
   * @param {function} onClick - click event handler
   * @returns {Element} Wrapper <div>.
   */
  function createEnterVRButton (onClick) {
    var vrButton;
    var wrapper;
  
    // Create elements.
    wrapper = document.createElement('div');
    wrapper.classList.add(ENTER_VR_CLASS);
    wrapper.setAttribute(constants.AFRAME_INJECTED, '');
    vrButton = document.createElement('button');
    vrButton.className = ENTER_VR_BTN_CLASS;
    vrButton.setAttribute('title',
      'Enter VR mode with a headset or fullscreen mode on a desktop. ' +
      'Visit https://webvr.rocks or https://webvr.info for more information.');
    vrButton.setAttribute(constants.AFRAME_INJECTED, '');
    if (utils.device.isMobile()) { applyStickyHoverFix(vrButton); }
    // Insert elements.
    wrapper.appendChild(vrButton);
    vrButton.addEventListener('click', function (evt) {
      onClick();
      evt.stopPropagation();
    });
    return wrapper;
  }
  
  /**
   * Create a button that when clicked will enter into AR mode
   *
   * Structure: <div><button></div>
   *
   * @param {function} onClick - click event handler
   * @returns {Element} Wrapper <div>.
   */
  function createEnterARButton (onClick) {
    var arButton;
    var wrapper;
  
    // Create elements.
    wrapper = document.createElement('div');
    wrapper.classList.add(ENTER_AR_CLASS);
    wrapper.setAttribute(constants.AFRAME_INJECTED, '');
    arButton = document.createElement('button');
    arButton.className = ENTER_AR_BTN_CLASS;
    arButton.setAttribute('title',
      'Enter AR mode with a headset or handheld device. ' +
      'Visit https://webvr.rocks or https://webvr.info for more information.');
    arButton.setAttribute(constants.AFRAME_INJECTED, '');
    if (utils.device.isMobile()) { applyStickyHoverFix(arButton); }
    // Insert elements.
    wrapper.appendChild(arButton);
    arButton.addEventListener('click', function (evt) {
      onClick();
      evt.stopPropagation();
    });
    return wrapper;
  }
  
  /**
   * Creates a modal dialog to request the user to switch to landscape orientation.
   *
   * @param {function} onClick - click event handler
   * @returns {Element} Wrapper <div>.
   */
  function createOrientationModal (onClick) {
    var modal = document.createElement('div');
    modal.className = ORIENTATION_MODAL_CLASS;
    modal.classList.add(HIDDEN_CLASS);
    modal.setAttribute(constants.AFRAME_INJECTED, '');
  
    var exit = document.createElement('button');
    exit.setAttribute(constants.AFRAME_INJECTED, '');
    exit.innerHTML = 'Exit VR';
  
    // Exit VR on close.
    exit.addEventListener('click', onClick);
  
    modal.appendChild(exit);
  
    return modal;
  }
  
  /**
   * CSS hover state is sticky in iOS (as in 12/18/2019)
   * They are not removed on mouseleave and this function applies a class
   * to resets the style.
   *
   * @param {function} buttonEl - Button element
   */
  function applyStickyHoverFix (buttonEl) {
    buttonEl.addEventListener('touchstart', function () {
      buttonEl.classList.remove('resethover');
    });
    buttonEl.addEventListener('touchend', function () {
      buttonEl.classList.add('resethover');
    });
  }
  