// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

<include src="../../../../ui/webui/resources/js/cr/ui/focus_row.js">
<include src="../../../../ui/webui/resources/js/cr/ui/focus_grid.js">
<include src="../uber/uber_utils.js">
<include src="drag_and_drop_handler.js">
<include src="extension_code.js">
<include src="extension_commands_overlay.js">
<include src="extension_error_overlay.js">
<include src="extension_focus_manager.js">
<include src="focus_row.js">
<include src="extension_list.js">
<include src="pack_extension_overlay.js">
<include src="extension_loader.js">
<include src="extension_options_overlay.js">

<if expr="chromeos">
<include src="chromeos/kiosk_apps.js">
</if>

// Used for observing function of the backend datasource for this page by
// tests.
var webuiResponded = false;

cr.define('extensions', function() {
  var ExtensionList = extensions.ExtensionList;

  /**
   * ExtensionSettings class
   * @class
   * @constructor
   * @implements {extensions.ExtensionListDelegate}
   */
  function ExtensionSettings() {}

  cr.addSingletonGetter(ExtensionSettings);

  ExtensionSettings.prototype = {
    /**
     * The drag-drop wrapper for installing external Extensions, if available.
     * null if external Extension installation is not available.
     * @type {cr.ui.DragWrapper}
     * @private
     */
    dragWrapper_: null,

    /**
     * True if drag-drop is both available and currently enabled - it can be
     * temporarily disabled while overlays are showing.
     * @type {boolean}
     * @private
     */
    dragEnabled_: false,

    /**
     * True if the page has finished the initial load.
     * @private {boolean}
     */
    hasLoaded_: false,

    /**
     * Perform initial setup.
     */
    initialize: function() {
      this.setLoading_(true);
      uber.onContentFrameLoaded();
      cr.ui.FocusOutlineManager.forDocument(document);
      measureCheckboxStrings();

      // Set the title.
      uber.setTitle(loadTimeData.getString('extensionSettings'));

      var extensionList = new ExtensionList(this);
      extensionList.id = 'extension-settings-list';
      var wrapper = $('extension-list-wrapper');
      wrapper.insertBefore(extensionList, wrapper.firstChild);

      // Get the initial profile state, and register to be notified of any
      // future changes.
      chrome.developerPrivate.getProfileConfiguration(
          this.update_.bind(this));
      chrome.developerPrivate.onProfileStateChanged.addListener(
          this.update_.bind(this));

      var extensionLoader = extensions.ExtensionLoader.getInstance();

      $('toggle-dev-on').addEventListener('change', function(e) {
        this.updateDevControlsVisibility_(true);
        chrome.developerPrivate.updateProfileConfiguration(
            {inDeveloperMode: e.target.checked});
        var suffix = $('toggle-dev-on').checked ? 'Enabled' : 'Disabled';
        chrome.send('metricsHandler:recordAction',
                    ['Options_ToggleDeveloperMode_' + suffix]);
      }.bind(this));

      window.addEventListener('resize', function() {
        this.updateDevControlsVisibility_(false);
      }.bind(this));

      // Set up the three dev mode buttons (load unpacked, pack and update).
      $('load-unpacked').addEventListener('click', function(e) {
        chrome.send('metricsHandler:recordAction',
                    ['Options_LoadUnpackedExtension']);
        extensionLoader.loadUnpacked();
      });
      $('pack-extension').addEventListener('click',
          this.handlePackExtension_.bind(this));
      $('update-extensions-now').addEventListener('click',
          this.handleUpdateExtensionNow_.bind(this));

      if (!loadTimeData.getBoolean('offStoreInstallEnabled')) {
        var dragTarget = document.documentElement;
        /** @private {extensions.DragAndDropHandler} */
        this.dragWrapperHandler_ =
            new extensions.DragAndDropHandler(true, dragTarget);
        dragTarget.addEventListener('extension-drag-started', function() {
          ExtensionSettings.showOverlay($('drop-target-overlay'));
        });
        dragTarget.addEventListener('extension-drag-ended', function() {
          var overlay = ExtensionSettings.getCurrentOverlay();
          if (overlay && overlay.id === 'drop-target-overlay')
            ExtensionSettings.showOverlay(null);
        });
        this.dragWrapper_ =
            new cr.ui.DragWrapper(dragTarget, this.dragWrapperHandler_);
      }

      extensions.PackExtensionOverlay.getInstance().initializePage();

      // Hook up the configure commands link to the overlay.
      var link = document.querySelector('.extension-commands-config');
      link.addEventListener('click',
          this.handleExtensionCommandsConfig_.bind(this));

      // Initialize the Commands overlay.
      extensions.ExtensionCommandsOverlay.getInstance().initializePage();

      extensions.ExtensionErrorOverlay.getInstance().initializePage(
          extensions.ExtensionSettings.showOverlay);

      extensions.ExtensionOptionsOverlay.getInstance().initializePage(
          extensions.ExtensionSettings.showOverlay);

      // Add user action logging for bottom links.
      var moreExtensionLink =
          document.getElementsByClassName('more-extensions-link');
      for (var i = 0; i < moreExtensionLink.length; i++) {
        moreExtensionLink[i].addEventListener('click', function(e) {
          chrome.send('metricsHandler:recordAction',
                      ['Options_GetMoreExtensions']);
        });
      }

      // Initialize the kiosk overlay.
      if (cr.isChromeOS) {
        var kioskOverlay = extensions.KioskAppsOverlay.getInstance();
        kioskOverlay.initialize();

        $('add-kiosk-app').addEventListener('click', function() {
          ExtensionSettings.showOverlay($('kiosk-apps-page'));
          kioskOverlay.didShowPage();
        });

        extensions.KioskDisableBailoutConfirm.getInstance().initialize();
      }

      cr.ui.overlay.setupOverlay($('drop-target-overlay'));
      cr.ui.overlay.globalInitialization();

      extensions.ExtensionFocusManager.getInstance().initialize();

      var path = document.location.pathname;
      if (path.length > 1) {
        // Skip starting slash and remove trailing slash (if any).
        var overlayName = path.slice(1).replace(/\/$/, '');
        if (overlayName == 'configureCommands')
          this.showExtensionCommandsConfigUi_();
      }
    },

    /**
     * [Re]-Populates the page with data representing the current state of
     * installed extensions.
     * @param {chrome.developerPrivate.ProfileInfo} profileInfo
     * @private
     */
    update_: function(profileInfo) {
      // We only set the page to be loading if we haven't already finished an
      // initial load, because otherwise the updates are all incremental and
      // don't need to display the interstitial spinner.
      if (!this.hasLoaded_)
        this.setLoading_(true);
      webuiResponded = true;

      /** @const */
      var supervised = profileInfo.isSupervised;

      var pageDiv = $('extension-settings');
      pageDiv.classList.toggle('profile-is-supervised', supervised);
      pageDiv.classList.toggle('showing-banner', supervised);

      var devControlsCheckbox = $('toggle-dev-on');
      devControlsCheckbox.checked = profileInfo.inDeveloperMode;
      devControlsCheckbox.disabled = supervised;

      $('load-unpacked').disabled = !profileInfo.canLoadUnpacked;
      var extensionList = $('extension-settings-list');
      extensionList.updateExtensionsData(
          profileInfo.isIncognitoAvailable,
          profileInfo.appInfoDialogEnabled).then(function() {
        if (!this.hasLoaded_) {
          this.hasLoaded_ = true;
          this.setLoading_(false);
        }
        this.onExtensionCountChanged();
      }.bind(this));
    },

    /**
     * Shows the loading spinner and hides elements that shouldn't be visible
     * while loading.
     * @param {boolean} isLoading
     * @private
     */
    setLoading_: function(isLoading) {
      document.documentElement.classList.toggle('loading', isLoading);
      $('loading-spinner').hidden = !isLoading;
      $('dev-controls').hidden = isLoading;
      this.updateDevControlsVisibility_(false);

      // The extension list is already hidden/shown elsewhere and shouldn't be
      // updated here because it can be hidden if there are no extensions.
    },

    /**
     * Handles the Pack Extension button.
     * @param {Event} e Change event.
     * @private
     */
    handlePackExtension_: function(e) {
      ExtensionSettings.showOverlay($('pack-extension-overlay'));
      chrome.send('metricsHandler:recordAction', ['Options_PackExtension']);
    },

    /**
     * Shows the Extension Commands configuration UI.
     * @private
     */
    showExtensionCommandsConfigUi_: function() {
      ExtensionSettings.showOverlay($('extension-commands-overlay'));
      chrome.send('metricsHandler:recordAction',
                  ['Options_ExtensionCommands']);
    },

    /**
     * Handles the Configure (Extension) Commands link.
     * @param {Event} e Change event.
     * @private
     */
    handleExtensionCommandsConfig_: function(e) {
      this.showExtensionCommandsConfigUi_();
    },

    /**
     * Handles the Update Extension Now button.
     * @param {Event} e Change event.
     * @private
     */
    handleUpdateExtensionNow_: function(e) {
      chrome.developerPrivate.autoUpdate();
      chrome.send('metricsHandler:recordAction',
                  ['Options_UpdateExtensions']);
    },

    /**
     * Updates the visibility of the developer controls based on whether the
     * [x] Developer mode checkbox is checked.
     * @param {boolean} animated Whether to animate any updates.
     * @private
     */
    updateDevControlsVisibility_: function(animated) {
      var showDevControls = $('toggle-dev-on').checked;
      $('extension-settings').classList.toggle('dev-mode', showDevControls);

      var devControls = $('dev-controls');
      devControls.classList.toggle('animated', animated);

      var buttons = devControls.querySelector('.button-container');
      Array.prototype.forEach.call(buttons.querySelectorAll('a, button'),
                                   function(control) {
        control.tabIndex = showDevControls ? 0 : -1;
      });
      buttons.setAttribute('aria-hidden', !showDevControls);

      window.requestAnimationFrame(function() {
        devControls.style.height = !showDevControls ? '' :
            buttons.offsetHeight + 'px';

        document.dispatchEvent(new Event('devControlsVisibilityUpdated'));
      }.bind(this));
    },

    /** @override */
    onExtensionCountChanged: function() {
      /** @const */
      var hasExtensions = $('extension-settings-list').getNumExtensions() != 0;
      $('no-extensions').hidden = hasExtensions;
      $('extension-list-wrapper').hidden = !hasExtensions;
    },
  };

  /**
   * Returns the current overlay or null if one does not exist.
   * @return {Element} The overlay element.
   */
  ExtensionSettings.getCurrentOverlay = function() {
    return document.querySelector('#overlay .page.showing');
  };

  /**
   * Sets the given overlay to show. If the overlay is already showing, this is
   * a no-op; otherwise, hides any currently-showing overlay.
   * @param {HTMLElement} node The overlay page to show. If null, all overlays
   *     are hidden.
   */
  ExtensionSettings.showOverlay = function(node) {
    var pageDiv = $('extension-settings');
    pageDiv.style.width = node ? window.getComputedStyle(pageDiv).width : '';
    document.body.classList.toggle('no-scroll', !!node);

    var currentlyShowingOverlay = ExtensionSettings.getCurrentOverlay();
    if (currentlyShowingOverlay) {
      if (currentlyShowingOverlay == node)  // Already displayed.
        return;
      currentlyShowingOverlay.classList.remove('showing');
    }

    if (node) {
      var lastFocused;

      var focusOutlineManager = cr.ui.FocusOutlineManager.forDocument(document);
      if (focusOutlineManager.visible)
        lastFocused = document.activeElement;

      $('overlay').addEventListener('cancelOverlay', function f() {
        if (lastFocused && focusOutlineManager.visible)
          lastFocused.focus();

        $('overlay').removeEventListener('cancelOverlay', f);
        uber.replaceState({}, '');
      });
      node.classList.add('showing');
    }

    var pages = document.querySelectorAll('.page');
    for (var i = 0; i < pages.length; i++) {
      pages[i].setAttribute('aria-hidden', node ? 'true' : 'false');
    }

    $('overlay').hidden = !node;

    if (node)
      ExtensionSettings.focusOverlay();

    // If drag-drop for external Extension installation is available, enable
    // drag-drop when there is any overlay showing other than the usual overlay
    // shown when drag-drop is started.
    var settings = ExtensionSettings.getInstance();
    if (settings.dragWrapper_) {
      assert(settings.dragWrapperHandler_).dragEnabled =
          !node || node == $('drop-target-overlay');
    }

    uber.invokeMethodOnParent(node ? 'beginInterceptingEvents' :
                                     'stopInterceptingEvents');
  };

  ExtensionSettings.focusOverlay = function() {
    var currentlyShowingOverlay = ExtensionSettings.getCurrentOverlay();
    assert(currentlyShowingOverlay);

    if (cr.ui.FocusOutlineManager.forDocument(document).visible)
      cr.ui.setInitialFocus(currentlyShowingOverlay);

    if (!currentlyShowingOverlay.contains(document.activeElement)) {
      // Make sure focus isn't stuck behind the overlay.
      document.activeElement.blur();
    }
  };

  /**
   * Utility function to find the width of various UI strings and synchronize
   * the width of relevant spans. This is crucial for making sure the
   * Enable/Enabled checkboxes align, as well as the Developer Mode checkbox.
   */
  function measureCheckboxStrings() {
    var trashWidth = 30;
    var measuringDiv = $('font-measuring-div');
    measuringDiv.textContent =
        loadTimeData.getString('extensionSettingsEnabled');
    measuringDiv.className = 'enabled-text';
    var pxWidth = measuringDiv.clientWidth + trashWidth;
    measuringDiv.textContent =
        loadTimeData.getString('extensionSettingsEnable');
    measuringDiv.className = 'enable-text';
    pxWidth = Math.max(measuringDiv.clientWidth + trashWidth, pxWidth);
    measuringDiv.textContent =
        loadTimeData.getString('extensionSettingsDeveloperMode');
    measuringDiv.className = '';
    pxWidth = Math.max(measuringDiv.clientWidth, pxWidth);

    var style = document.createElement('style');
    style.type = 'text/css';
    style.textContent =
        '.enable-checkbox-text {' +
        '  min-width: ' + (pxWidth - trashWidth) + 'px;' +
        '}' +
        '#dev-toggle span {' +
        '  min-width: ' + pxWidth + 'px;' +
        '}';
    document.querySelector('head').appendChild(style);
  };

  // Export
  return {
    ExtensionSettings: ExtensionSettings
  };
});

window.addEventListener('load', function(e) {
  extensions.ExtensionSettings.getInstance().initialize();
});
