/*
 * Copyright (C) 2006, 2007, 2008 Apple Inc.  All rights reserved.
 * Copyright (C) 2007 Matt Lilek (pewtermoose@gmail.com).
 * Copyright (C) 2009 Joseph Pecoraro
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1.  Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 * 2.  Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
 *     its contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

/**
 * @unrestricted
 */
Main.Main = class {
  /**
   * @suppressGlobalPropertiesCheck
   */
  constructor() {
    Main.Main._instanceForTest = this;
    runOnWindowLoad(this._loaded.bind(this));
  }

  /**
   * @param {string} label
   */
  static time(label) {
    if (Host.isUnderTest())
      return;
    console.time(label);
  }

  /**
   * @param {string} label
   */
  static timeEnd(label) {
    if (Host.isUnderTest())
      return;
    console.timeEnd(label);
  }

  async _loaded() {
    console.timeStamp('Main._loaded');
    await Runtime.runtimeReady();
    Runtime.setPlatform(Host.platform());
    InspectorFrontendHost.getPreferences(this._gotPreferences.bind(this));
  }

  /**
   * @param {!Object<string, string>} prefs
   */
  _gotPreferences(prefs) {
    console.timeStamp('Main._gotPreferences');
    if (Host.isUnderTest(prefs))
      self.runtime.useTestBase();
    this._createSettings(prefs);
    this._createAppUI();
  }

  /**
   * @param {!Object<string, string>} prefs
   * Note: this function is called from testSettings in Tests.js.
   */
  _createSettings(prefs) {
    this._initializeExperiments();
    let storagePrefix = '';
    if (Host.isCustomDevtoolsFrontend())
      storagePrefix = '__custom__';
    else if (!Runtime.queryParam('can_dock') && !!Runtime.queryParam('debugFrontend') && !Host.isUnderTest())
      storagePrefix = '__bundled__';

    let localStorage;
    if (!Host.isUnderTest() && window.localStorage) {
      localStorage = new Common.SettingsStorage(
          window.localStorage, undefined, undefined, () => window.localStorage.clear(), storagePrefix);
    } else {
      localStorage = new Common.SettingsStorage({}, undefined, undefined, undefined, storagePrefix);
    }
    const globalStorage = new Common.SettingsStorage(
        prefs, InspectorFrontendHost.setPreference, InspectorFrontendHost.removePreference,
        InspectorFrontendHost.clearPreferences, storagePrefix);
    Common.settings = new Common.Settings(globalStorage, localStorage);
    if (!Host.isUnderTest())
      new Common.VersionController().updateVersion();
  }

  _initializeExperiments() {
    // Keep this sorted alphabetically: both keys and values.
    Runtime.experiments.register('applyCustomStylesheet', 'Allow custom UI themes');
    Runtime.experiments.register('blackboxJSFramesOnTimeline', 'Blackbox JavaScript frames on Timeline', true);
    Runtime.experiments.register('colorContrastRatio', 'Color contrast ratio line in color picker', true);
    Runtime.experiments.register('consoleBelowPrompt', 'Eager evaluation');
    Runtime.experiments.register('emptySourceMapAutoStepping', 'Empty sourcemap auto-stepping');
    Runtime.experiments.register('inputEventsOnTimelineOverview', 'Input events on Timeline overview', true);
    Runtime.experiments.register('nativeHeapProfiler', 'Native memory sampling heap profiler', true);
    Runtime.experiments.register('networkSearch', 'Network search');
    Runtime.experiments.register('oopifInlineDOM', 'OOPIF: inline DOM ', true);
    Runtime.experiments.register('protocolMonitor', 'Protocol Monitor');
    Runtime.experiments.register('sourceDiff', 'Source diff');
    Runtime.experiments.register('sourcesPrettyPrint', 'Automatically pretty print in the Sources Panel');
    Runtime.experiments.register(
        'stepIntoAsync', 'Introduce separate step action, stepInto becomes powerful enough to go inside async call');
    Runtime.experiments.register('splitInDrawer', 'Split in drawer', true);
    Runtime.experiments.register('terminalInDrawer', 'Terminal in drawer', true);

    // Timeline
    Runtime.experiments.register('timelineEventInitiators', 'Timeline: event initiators');
    Runtime.experiments.register('timelineFlowEvents', 'Timeline: flow events', true);
    Runtime.experiments.register('timelineInvalidationTracking', 'Timeline: invalidation tracking', true);
    Runtime.experiments.register('timelinePaintTimingMarkers', 'Timeline: paint timing markers', true);
    Runtime.experiments.register('timelineShowAllEvents', 'Timeline: show all events', true);
    Runtime.experiments.register('timelineTracingJSProfile', 'Timeline: tracing based JS profiler', true);
    Runtime.experiments.register('timelineV8RuntimeCallStats', 'Timeline: V8 Runtime Call Stats on Timeline', true);

    Runtime.experiments.cleanUpStaleExperiments();

    if (Host.isUnderTest()) {
      const testPath = Runtime.queryParam('test');
      // Enable experiments for testing.
      if (testPath.indexOf('oopif/') !== -1)
        Runtime.experiments.enableForTest('oopifInlineDOM');
      if (testPath.indexOf('network/') !== -1)
        Runtime.experiments.enableForTest('networkSearch');
      if (testPath.indexOf('console/viewport-testing/') !== -1)
        Runtime.experiments.enableForTest('consoleBelowPrompt');
    }

    Runtime.experiments.setDefaultExperiments(
        ['colorContrastRatio', 'stepIntoAsync', 'oopifInlineDOM', 'consoleBelowPrompt']);
  }

  /**
   * @suppressGlobalPropertiesCheck
   */
  async _createAppUI() {
    Main.Main.time('Main._createAppUI');

    UI.viewManager = new UI.ViewManager();

    // Request filesystems early, we won't create connections until callback is fired. Things will happen in parallel.
    Persistence.isolatedFileSystemManager = new Persistence.IsolatedFileSystemManager();

    const themeSetting = Common.settings.createSetting('uiTheme', 'default');
    UI.initializeUIUtils(document, themeSetting);
    themeSetting.addChangeListener(Components.reload.bind(Components));

    UI.installComponentRootStyles(/** @type {!Element} */ (document.body));

    this._addMainEventListeners(document);

    const canDock = !!Runtime.queryParam('can_dock');
    UI.zoomManager = new UI.ZoomManager(window, InspectorFrontendHost);
    UI.inspectorView = UI.InspectorView.instance();
    UI.ContextMenu.initialize();
    UI.ContextMenu.installHandler(document);
    UI.Tooltip.installHandler(document);
    Components.dockController = new Components.DockController(canDock);
    SDK.consoleModel = new SDK.ConsoleModel();
    SDK.multitargetNetworkManager = new SDK.MultitargetNetworkManager();
    SDK.domDebuggerManager = new SDK.DOMDebuggerManager();
    SDK.targetManager.addEventListener(
        SDK.TargetManager.Events.SuspendStateChanged, this._onSuspendStateChanged.bind(this));

    UI.shortcutsScreen = new UI.ShortcutsScreen();
    // set order of some sections explicitly
    UI.shortcutsScreen.section(Common.UIString('Elements Panel'));
    UI.shortcutsScreen.section(Common.UIString('Styles Pane'));
    UI.shortcutsScreen.section(Common.UIString('Debugger'));
    UI.shortcutsScreen.section(Common.UIString('Console'));

    Workspace.fileManager = new Workspace.FileManager();
    Workspace.workspace = new Workspace.Workspace();

    Bindings.networkProjectManager = new Bindings.NetworkProjectManager();
    Bindings.resourceMapping = new Bindings.ResourceMapping(SDK.targetManager, Workspace.workspace);
    new Bindings.PresentationConsoleMessageManager();
    Bindings.cssWorkspaceBinding = new Bindings.CSSWorkspaceBinding(SDK.targetManager, Workspace.workspace);
    Bindings.debuggerWorkspaceBinding = new Bindings.DebuggerWorkspaceBinding(SDK.targetManager, Workspace.workspace);
    Bindings.breakpointManager =
        new Bindings.BreakpointManager(Workspace.workspace, SDK.targetManager, Bindings.debuggerWorkspaceBinding);
    Extensions.extensionServer = new Extensions.ExtensionServer();

    new Persistence.FileSystemWorkspaceBinding(Persistence.isolatedFileSystemManager, Workspace.workspace);
    Persistence.persistence = new Persistence.Persistence(Workspace.workspace, Bindings.breakpointManager);
    Persistence.networkPersistenceManager = new Persistence.NetworkPersistenceManager(Workspace.workspace);

    new Main.ExecutionContextSelector(SDK.targetManager, UI.context);
    Bindings.blackboxManager = new Bindings.BlackboxManager(Bindings.debuggerWorkspaceBinding);

    new Main.Main.PauseListener();

    UI.actionRegistry = new UI.ActionRegistry();
    UI.shortcutRegistry = new UI.ShortcutRegistry(UI.actionRegistry, document);
    UI.ShortcutsScreen.registerShortcuts();
    this._registerForwardedShortcuts();
    this._registerMessageSinkListener();

    Main.Main.timeEnd('Main._createAppUI');
    this._showAppUI(await self.runtime.extension(Common.AppProvider).instance());
  }

  /**
   * @param {!Object} appProvider
   * @suppressGlobalPropertiesCheck
   */
  _showAppUI(appProvider) {
    Main.Main.time('Main._showAppUI');
    const app = /** @type {!Common.AppProvider} */ (appProvider).createApp();
    // It is important to kick controller lifetime after apps are instantiated.
    Components.dockController.initialize();
    app.presentUI(document);

    const toggleSearchNodeAction = UI.actionRegistry.action('elements.toggle-element-search');
    // TODO: we should not access actions from other modules.
    if (toggleSearchNodeAction) {
      InspectorFrontendHost.events.addEventListener(
          InspectorFrontendHostAPI.Events.EnterInspectElementMode,
          toggleSearchNodeAction.execute.bind(toggleSearchNodeAction), this);
    }
    InspectorFrontendHost.events.addEventListener(
        InspectorFrontendHostAPI.Events.RevealSourceLine, this._revealSourceLine, this);

    UI.inspectorView.createToolbars();
    InspectorFrontendHost.loadCompleted();

    const extensions = self.runtime.extensions(Common.QueryParamHandler);
    for (const extension of extensions) {
      const value = Runtime.queryParam(extension.descriptor()['name']);
      if (value !== null)
        extension.instance().then(handleQueryParam.bind(null, value));
    }

    /**
     * @param {string} value
     * @param {!Common.QueryParamHandler} handler
     */
    function handleQueryParam(value, handler) {
      handler.handleQueryParam(value);
    }

    // Allow UI cycles to repaint prior to creating connection.
    setTimeout(this._initializeTarget.bind(this), 0);
    Main.Main.timeEnd('Main._showAppUI');
  }

  async _initializeTarget() {
    Main.Main.time('Main._initializeTarget');
    const instances =
        await Promise.all(self.runtime.extensions('early-initialization').map(extension => extension.instance()));
    for (const instance of instances)
      /** @type {!Common.Runnable} */ (instance).run();
    // Used for browser tests.
    InspectorFrontendHost.readyForTest();
    // Asynchronously run the extensions.
    setTimeout(this._lateInitialization.bind(this), 100);
    Main.Main.timeEnd('Main._initializeTarget');
  }

  _lateInitialization() {
    Main.Main.time('Main._lateInitialization');
    this._registerShortcuts();
    Extensions.extensionServer.initializeExtensions();
    if (!Host.isUnderTest()) {
      for (const extension of self.runtime.extensions('late-initialization'))
        extension.instance().then(instance => (/** @type {!Common.Runnable} */ (instance)).run());
    }
    Main.Main.timeEnd('Main._lateInitialization');
  }

  _registerForwardedShortcuts() {
    /** @const */ const forwardedActions = [
      'main.toggle-dock', 'debugger.toggle-breakpoints-active', 'debugger.toggle-pause', 'commandMenu.show',
      'console.show'
    ];
    const actionKeys =
        UI.shortcutRegistry.keysForActions(forwardedActions).map(UI.KeyboardShortcut.keyCodeAndModifiersFromKey);
    InspectorFrontendHost.setWhitelistedShortcuts(JSON.stringify(actionKeys));
  }

  _registerMessageSinkListener() {
    Common.console.addEventListener(Common.Console.Events.MessageAdded, messageAdded);

    /**
     * @param {!Common.Event} event
     */
    function messageAdded(event) {
      const message = /** @type {!Common.Console.Message} */ (event.data);
      if (message.show)
        Common.console.show();
    }
  }

  /**
   * @param {!Common.Event} event
   */
  _revealSourceLine(event) {
    const url = /** @type {string} */ (event.data['url']);
    const lineNumber = /** @type {number} */ (event.data['lineNumber']);
    const columnNumber = /** @type {number} */ (event.data['columnNumber']);

    const uiSourceCode = Workspace.workspace.uiSourceCodeForURL(url);
    if (uiSourceCode) {
      Common.Revealer.reveal(uiSourceCode.uiLocation(lineNumber, columnNumber));
      return;
    }

    /**
     * @param {!Common.Event} event
     */
    function listener(event) {
      const uiSourceCode = /** @type {!Workspace.UISourceCode} */ (event.data);
      if (uiSourceCode.url() === url) {
        Common.Revealer.reveal(uiSourceCode.uiLocation(lineNumber, columnNumber));
        Workspace.workspace.removeEventListener(Workspace.Workspace.Events.UISourceCodeAdded, listener);
      }
    }

    Workspace.workspace.addEventListener(Workspace.Workspace.Events.UISourceCodeAdded, listener);
  }

  _registerShortcuts() {
    const shortcut = UI.KeyboardShortcut;
    const section = UI.shortcutsScreen.section(Common.UIString('All Panels'));
    let keys = [
      shortcut.makeDescriptor('[', shortcut.Modifiers.CtrlOrMeta),
      shortcut.makeDescriptor(']', shortcut.Modifiers.CtrlOrMeta)
    ];
    section.addRelatedKeys(keys, Common.UIString('Go to the panel to the left/right'));

    const toggleConsoleLabel = Common.UIString('Show console');
    section.addKey(shortcut.makeDescriptor(shortcut.Keys.Tilde, shortcut.Modifiers.Ctrl), toggleConsoleLabel);
    section.addKey(shortcut.makeDescriptor(shortcut.Keys.Esc), Common.UIString('Toggle drawer'));
    if (Components.dockController.canDock()) {
      section.addKey(
          shortcut.makeDescriptor('M', shortcut.Modifiers.CtrlOrMeta | shortcut.Modifiers.Shift),
          Common.UIString('Toggle device mode'));
      section.addKey(
          shortcut.makeDescriptor('D', shortcut.Modifiers.CtrlOrMeta | shortcut.Modifiers.Shift),
          Common.UIString('Toggle dock side'));
    }
    section.addKey(shortcut.makeDescriptor('f', shortcut.Modifiers.CtrlOrMeta), Common.UIString('Search'));

    const advancedSearchShortcutModifier = Host.isMac() ?
        UI.KeyboardShortcut.Modifiers.Meta | UI.KeyboardShortcut.Modifiers.Alt :
        UI.KeyboardShortcut.Modifiers.Ctrl | UI.KeyboardShortcut.Modifiers.Shift;
    const advancedSearchShortcut = shortcut.makeDescriptor('f', advancedSearchShortcutModifier);
    section.addKey(advancedSearchShortcut, Common.UIString('Search across all sources'));

    const inspectElementModeShortcuts =
        UI.shortcutRegistry.shortcutDescriptorsForAction('elements.toggle-element-search');
    if (inspectElementModeShortcuts.length)
      section.addKey(inspectElementModeShortcuts[0], Common.UIString('Select node to inspect'));

    const openResourceShortcut = UI.KeyboardShortcut.makeDescriptor('p', UI.KeyboardShortcut.Modifiers.CtrlOrMeta);
    section.addKey(openResourceShortcut, Common.UIString('Go to source'));

    if (Host.isMac()) {
      keys = [
        shortcut.makeDescriptor('g', shortcut.Modifiers.Meta),
        shortcut.makeDescriptor('g', shortcut.Modifiers.Meta | shortcut.Modifiers.Shift)
      ];
      section.addRelatedKeys(keys, Common.UIString('Find next/previous'));
    }
  }

  _postDocumentKeyDown(event) {
    if (!event.handled)
      UI.shortcutRegistry.handleShortcut(event);
  }

  /**
   * @param {!Event} event
   */
  _redispatchClipboardEvent(event) {
    const eventCopy = new CustomEvent('clipboard-' + event.type, {bubbles: true});
    eventCopy['original'] = event;
    const document = event.target && event.target.ownerDocument;
    const target = document ? document.deepActiveElement() : null;
    if (target)
      target.dispatchEvent(eventCopy);
    if (eventCopy.handled)
      event.preventDefault();
  }

  _contextMenuEventFired(event) {
    if (event.handled || event.target.classList.contains('popup-glasspane'))
      event.preventDefault();
  }

  /**
   * @param {!Document} document
   */
  _addMainEventListeners(document) {
    document.addEventListener('keydown', this._postDocumentKeyDown.bind(this), false);
    document.addEventListener('beforecopy', this._redispatchClipboardEvent.bind(this), true);
    document.addEventListener('copy', this._redispatchClipboardEvent.bind(this), false);
    document.addEventListener('cut', this._redispatchClipboardEvent.bind(this), false);
    document.addEventListener('paste', this._redispatchClipboardEvent.bind(this), false);
    document.addEventListener('contextmenu', this._contextMenuEventFired.bind(this), true);
  }

  _onSuspendStateChanged() {
    const suspended = SDK.targetManager.allTargetsSuspended();
    UI.inspectorView.onSuspendStateChanged(suspended);
  }
};

/**
 * @implements {UI.ActionDelegate}
 * @unrestricted
 */
Main.Main.ZoomActionDelegate = class {
  /**
   * @override
   * @param {!UI.Context} context
   * @param {string} actionId
   * @return {boolean}
   */
  handleAction(context, actionId) {
    if (InspectorFrontendHost.isHostedMode())
      return false;

    switch (actionId) {
      case 'main.zoom-in':
        InspectorFrontendHost.zoomIn();
        return true;
      case 'main.zoom-out':
        InspectorFrontendHost.zoomOut();
        return true;
      case 'main.zoom-reset':
        InspectorFrontendHost.resetZoom();
        return true;
    }
    return false;
  }
};

/**
 * @implements {UI.ActionDelegate}
 * @unrestricted
 */
Main.Main.SearchActionDelegate = class {
  /**
   * @override
   * @param {!UI.Context} context
   * @param {string} actionId
   * @return {boolean}
   * @suppressGlobalPropertiesCheck
   */
  handleAction(context, actionId) {
    const searchableView = UI.SearchableView.fromElement(document.deepActiveElement()) ||
        UI.inspectorView.currentPanelDeprecated().searchableView();
    if (!searchableView)
      return false;
    switch (actionId) {
      case 'main.search-in-panel.find':
        return searchableView.handleFindShortcut();
      case 'main.search-in-panel.cancel':
        return searchableView.handleCancelSearchShortcut();
      case 'main.search-in-panel.find-next':
        return searchableView.handleFindNextShortcut();
      case 'main.search-in-panel.find-previous':
        return searchableView.handleFindPreviousShortcut();
    }
    return false;
  }
};

/**
 * @implements {UI.ToolbarItem.Provider}
 */
Main.Main.MainMenuItem = class {
  constructor() {
    this._item = new UI.ToolbarMenuButton(this._handleContextMenu.bind(this), true);
    this._item.setTitle(Common.UIString('Customize and control DevTools'));
  }

  /**
   * @override
   * @return {?UI.ToolbarItem}
   */
  item() {
    return this._item;
  }

  /**
   * @param {!UI.ContextMenu} contextMenu
   */
  _handleContextMenu(contextMenu) {
    if (Components.dockController.canDock()) {
      const dockItemElement = createElementWithClass('div', 'flex-centered flex-auto');
      const titleElement = dockItemElement.createChild('span', 'flex-auto');
      titleElement.textContent = Common.UIString('Dock side');
      const toggleDockSideShorcuts = UI.shortcutRegistry.shortcutDescriptorsForAction('main.toggle-dock');
      titleElement.title = Common.UIString(
          'Placement of DevTools relative to the page. (%s to restore last position)', toggleDockSideShorcuts[0].name);
      dockItemElement.appendChild(titleElement);
      const dockItemToolbar = new UI.Toolbar('', dockItemElement);
      dockItemToolbar.makeBlueOnHover();
      const undock = new UI.ToolbarToggle(Common.UIString('Undock into separate window'), 'largeicon-undock');
      const bottom = new UI.ToolbarToggle(Common.UIString('Dock to bottom'), 'largeicon-dock-to-bottom');
      const right = new UI.ToolbarToggle(Common.UIString('Dock to right'), 'largeicon-dock-to-right');
      const left = new UI.ToolbarToggle(Common.UIString('Dock to left'), 'largeicon-dock-to-left');
      undock.addEventListener(UI.ToolbarButton.Events.MouseDown, event => event.data.consume());
      bottom.addEventListener(UI.ToolbarButton.Events.MouseDown, event => event.data.consume());
      right.addEventListener(UI.ToolbarButton.Events.MouseDown, event => event.data.consume());
      left.addEventListener(UI.ToolbarButton.Events.MouseDown, event => event.data.consume());
      undock.addEventListener(
          UI.ToolbarButton.Events.MouseUp, setDockSide.bind(null, Components.DockController.State.Undocked));
      bottom.addEventListener(
          UI.ToolbarButton.Events.MouseUp, setDockSide.bind(null, Components.DockController.State.DockedToBottom));
      right.addEventListener(
          UI.ToolbarButton.Events.MouseUp, setDockSide.bind(null, Components.DockController.State.DockedToRight));
      left.addEventListener(
          UI.ToolbarButton.Events.MouseUp, setDockSide.bind(null, Components.DockController.State.DockedToLeft));
      undock.setToggled(Components.dockController.dockSide() === Components.DockController.State.Undocked);
      bottom.setToggled(Components.dockController.dockSide() === Components.DockController.State.DockedToBottom);
      right.setToggled(Components.dockController.dockSide() === Components.DockController.State.DockedToRight);
      left.setToggled(Components.dockController.dockSide() === Components.DockController.State.DockedToLeft);
      dockItemToolbar.appendToolbarItem(undock);
      dockItemToolbar.appendToolbarItem(left);
      dockItemToolbar.appendToolbarItem(bottom);
      dockItemToolbar.appendToolbarItem(right);
      contextMenu.headerSection().appendCustomItem(dockItemElement);
    }

    /**
     * @param {string} side
     */
    function setDockSide(side) {
      Components.dockController.setDockSide(side);
      contextMenu.discard();
    }

    if (Components.dockController.dockSide() === Components.DockController.State.Undocked &&
        SDK.targetManager.mainTarget() && SDK.targetManager.mainTarget().hasBrowserCapability())
      contextMenu.defaultSection().appendAction('inspector_main.focus-debuggee', Common.UIString('Focus debuggee'));

    contextMenu.defaultSection().appendAction(
        'main.toggle-drawer',
        UI.inspectorView.drawerVisible() ? Common.UIString('Hide console drawer') :
                                           Common.UIString('Show console drawer'));
    contextMenu.appendItemsAtLocation('mainMenu');
    const moreTools = contextMenu.defaultSection().appendSubMenuItem(Common.UIString('More tools'));
    const extensions = self.runtime.extensions('view', undefined, true);
    for (const extension of extensions) {
      const descriptor = extension.descriptor();
      if (descriptor['persistence'] !== 'closeable')
        continue;
      if (descriptor['location'] !== 'drawer-view' && descriptor['location'] !== 'panel')
        continue;
      moreTools.defaultSection().appendItem(
          extension.title(), UI.viewManager.showView.bind(UI.viewManager, descriptor['id']));
    }

    const helpSubMenu = contextMenu.footerSection().appendSubMenuItem(Common.UIString('Help'));
    helpSubMenu.appendItemsAtLocation('mainMenuHelp');
  }
};

/**
 * @unrestricted
 */
Main.Main.PauseListener = class {
  constructor() {
    SDK.targetManager.addModelListener(
        SDK.DebuggerModel, SDK.DebuggerModel.Events.DebuggerPaused, this._debuggerPaused, this);
  }

  /**
   * @param {!Common.Event} event
   */
  _debuggerPaused(event) {
    SDK.targetManager.removeModelListener(
        SDK.DebuggerModel, SDK.DebuggerModel.Events.DebuggerPaused, this._debuggerPaused, this);
    const debuggerModel = /** @type {!SDK.DebuggerModel} */ (event.data);
    const debuggerPausedDetails = debuggerModel.debuggerPausedDetails();
    UI.context.setFlavor(SDK.Target, debuggerModel.target());
    Common.Revealer.reveal(debuggerPausedDetails);
  }
};

/**
 * @param {string} method
 * @param {?Object} params
 * @return {!Promise}
 */
Main.sendOverProtocol = function(method, params) {
  return new Promise((resolve, reject) => {
    Protocol.InspectorBackend.sendRawMessageForTesting(method, params, (err, ...results) => {
      if (err)
        return reject(err);
      return resolve(results);
    });
  });
};

/**
 * @implements {UI.ActionDelegate}
 * @unrestricted
 */
Main.ReloadActionDelegate = class {
  /**
   * @override
   * @param {!UI.Context} context
   * @param {string} actionId
   * @return {boolean}
   */
  handleAction(context, actionId) {
    switch (actionId) {
      case 'main.debug-reload':
        Components.reload();
        return true;
    }
    return false;
  }
};

new Main.Main();
