/*
 * Copyright (C) 2008 Apple Inc. All Rights Reserved.
 *
 * 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.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``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 INC. OR
 * 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.
 */

/**
 * @implements {UI.ContextFlavorListener}
 * @implements {UI.ListDelegate<!Sources.CallStackSidebarPane.Item>}
 * @unrestricted
 */
Sources.CallStackSidebarPane = class extends UI.SimpleView {
  constructor() {
    super(Common.UIString('Call Stack'), true);
    this.registerRequiredCSS('sources/callStackSidebarPane.css');

    this._blackboxedMessageElement = this._createBlackboxedMessageElement();
    this.contentElement.appendChild(this._blackboxedMessageElement);

    this._notPausedMessageElement = this.contentElement.createChild('div', 'gray-info-message');
    this._notPausedMessageElement.textContent = Common.UIString('Not paused');

    /** @type {!UI.ListModel<!Sources.CallStackSidebarPane.Item>} */
    this._items = new UI.ListModel();
    /** @type {!UI.ListControl<!Sources.CallStackSidebarPane.Item>} */
    this._list = new UI.ListControl(this._items, this, UI.ListMode.NonViewport);
    this.contentElement.appendChild(this._list.element);
    this._list.element.addEventListener('contextmenu', this._onContextMenu.bind(this), false);
    this._list.element.addEventListener('click', this._onClick.bind(this), false);

    this._showMoreMessageElement = this._createShowMoreMessageElement();
    this._showMoreMessageElement.classList.add('hidden');
    this.contentElement.appendChild(this._showMoreMessageElement);

    this._showBlackboxed = false;
    this._locationPool = new Bindings.LiveLocationPool();

    this._updateThrottler = new Common.Throttler(100);
    this._maxAsyncStackChainDepth = Sources.CallStackSidebarPane._defaultMaxAsyncStackChainDepth;
    this._update();

    this._updateItemThrottler = new Common.Throttler(100);
    this._scheduledForUpdateItems = new Set();
  }

  /**
   * @override
   * @param {?Object} object
   */
  flavorChanged(object) {
    this._showBlackboxed = false;
    this._maxAsyncStackChainDepth = Sources.CallStackSidebarPane._defaultMaxAsyncStackChainDepth;
    this._update();
  }

  _update() {
    this._updateThrottler.schedule(() => this._doUpdate());
  }

  /**
   * @return {!Promise<undefined>}
   */
  async _doUpdate() {
    this._locationPool.disposeAll();

    const details = UI.context.flavor(SDK.DebuggerPausedDetails);
    if (!details) {
      this._notPausedMessageElement.classList.remove('hidden');
      this._blackboxedMessageElement.classList.add('hidden');
      this._showMoreMessageElement.classList.add('hidden');
      this._items.replaceAll([]);
      UI.context.setFlavor(SDK.DebuggerModel.CallFrame, null);
      return;
    }

    let debuggerModel = details.debuggerModel;
    this._notPausedMessageElement.classList.add('hidden');

    const items = details.callFrames.map(frame => {
      const item = Sources.CallStackSidebarPane.Item.createForDebuggerCallFrame(
          frame, this._locationPool, this._refreshItem.bind(this));
      item[Sources.CallStackSidebarPane._debuggerCallFrameSymbol] = frame;
      return item;
    });

    let asyncStackTrace = details.asyncStackTrace;
    if (!asyncStackTrace && details.asyncStackTraceId) {
      if (details.asyncStackTraceId.debuggerId) {
        debuggerModel = SDK.DebuggerModel.modelForDebuggerId(details.asyncStackTraceId.debuggerId);
      }
      asyncStackTrace = debuggerModel ? await debuggerModel.fetchAsyncStackTrace(details.asyncStackTraceId) : null;
    }
    let peviousStackTrace = details.callFrames;
    let maxAsyncStackChainDepth = this._maxAsyncStackChainDepth;
    while (asyncStackTrace && maxAsyncStackChainDepth > 0) {
      let title = '';
      const isAwait = asyncStackTrace.description === 'async function';
      if (isAwait && peviousStackTrace.length && asyncStackTrace.callFrames.length) {
        const lastPreviousFrame = peviousStackTrace[peviousStackTrace.length - 1];
        const lastPreviousFrameName = UI.beautifyFunctionName(lastPreviousFrame.functionName);
        title = UI.asyncStackTraceLabel('await in ' + lastPreviousFrameName);
      } else {
        title = UI.asyncStackTraceLabel(asyncStackTrace.description);
      }

      items.push(...Sources.CallStackSidebarPane.Item.createItemsForAsyncStack(
          title, debuggerModel, asyncStackTrace.callFrames, this._locationPool, this._refreshItem.bind(this)));

      --maxAsyncStackChainDepth;
      peviousStackTrace = asyncStackTrace.callFrames;
      if (asyncStackTrace.parent) {
        asyncStackTrace = asyncStackTrace.parent;
      } else if (asyncStackTrace.parentId) {
        if (asyncStackTrace.parentId.debuggerId) {
          debuggerModel = SDK.DebuggerModel.modelForDebuggerId(asyncStackTrace.parentId.debuggerId);
        }
        asyncStackTrace = debuggerModel ? await debuggerModel.fetchAsyncStackTrace(asyncStackTrace.parentId) : null;
      } else {
        asyncStackTrace = null;
      }
    }
    this._showMoreMessageElement.classList.toggle('hidden', !asyncStackTrace);
    this._items.replaceAll(items);
    if (this._maxAsyncStackChainDepth === Sources.CallStackSidebarPane._defaultMaxAsyncStackChainDepth) {
      this._list.selectNextItem(true /* canWrap */, false /* center */);
    }
    this._updatedForTest();
  }

  _updatedForTest() {
  }

  /**
   * @param {!Sources.CallStackSidebarPane.Item} item
   */
  _refreshItem(item) {
    this._scheduledForUpdateItems.add(item);
    this._updateItemThrottler.schedule(innerUpdate.bind(this));

    /**
     * @this {!Sources.CallStackSidebarPane}
     * @return {!Promise<undefined>}
     */
    function innerUpdate() {
      const items = Array.from(this._scheduledForUpdateItems);
      this._scheduledForUpdateItems.clear();

      this._muteActivateItem = true;
      if (!this._showBlackboxed && this._items.every(item => item.isBlackboxed)) {
        this._showBlackboxed = true;
        for (let i = 0; i < this._items.length; ++i) {
          this._list.refreshItemByIndex(i);
        }
        this._blackboxedMessageElement.classList.toggle('hidden', true);
      } else {
        const itemsSet = new Set(items);
        let hasBlackboxed = false;
        for (let i = 0; i < this._items.length; ++i) {
          const item = this._items.at(i);
          if (itemsSet.has(item)) {
            this._list.refreshItemByIndex(i);
          }
          hasBlackboxed = hasBlackboxed || item.isBlackboxed;
        }
        this._blackboxedMessageElement.classList.toggle('hidden', this._showBlackboxed || !hasBlackboxed);
      }
      delete this._muteActivateItem;
      return Promise.resolve();
    }
  }

  /**
   * @override
   * @param {!Sources.CallStackSidebarPane.Item} item
   * @return {!Element}
   */
  createElementForItem(item) {
    const element = createElementWithClass('div', 'call-frame-item');
    const title = element.createChild('div', 'call-frame-item-title');
    title.createChild('div', 'call-frame-title-text').textContent = item.title;
    if (item.isAsyncHeader) {
      element.classList.add('async-header');
    } else {
      const linkElement = element.createChild('div', 'call-frame-location');
      linkElement.textContent = item.linkText.trimMiddle(30);
      linkElement.title = item.linkText;
      element.classList.toggle('blackboxed-call-frame', item.isBlackboxed);
    }
    element.classList.toggle('hidden', !this._showBlackboxed && item.isBlackboxed);
    element.appendChild(UI.Icon.create('smallicon-thick-right-arrow', 'selected-call-frame-icon'));
    return element;
  }

  /**
   * @override
   * @param {!Sources.CallStackSidebarPane.Item} item
   * @return {number}
   */
  heightForItem(item) {
    console.assert(false);  // Should not be called.
    return 0;
  }

  /**
   * @override
   * @param {!Sources.CallStackSidebarPane.Item} item
   * @return {boolean}
   */
  isItemSelectable(item) {
    return !!item[Sources.CallStackSidebarPane._debuggerCallFrameSymbol];
  }

  /**
   * @override
   * @param {?Sources.CallStackSidebarPane.Item} from
   * @param {?Sources.CallStackSidebarPane.Item} to
   * @param {?Element} fromElement
   * @param {?Element} toElement
   */
  selectedItemChanged(from, to, fromElement, toElement) {
    if (fromElement) {
      fromElement.classList.remove('selected');
    }
    if (toElement) {
      toElement.classList.add('selected');
    }
    if (to) {
      this._activateItem(to);
    }
  }

  /**
   * @override
   * @param {?Element} fromElement
   * @param {?Element} toElement
   * @return {boolean}
   */
  updateSelectedItemARIA(fromElement, toElement) {
    return false;
  }

  /**
   * @return {!Element}
   */
  _createBlackboxedMessageElement() {
    const element = createElementWithClass('div', 'blackboxed-message');
    element.createChild('span');
    const showAllLink = element.createChild('span', 'link');
    showAllLink.textContent = Common.UIString('Show blackboxed frames');
    showAllLink.addEventListener('click', () => {
      this._showBlackboxed = true;
      for (const item of this._items) {
        this._refreshItem(item);
      }
      this._blackboxedMessageElement.classList.toggle('hidden', true);
    });
    return element;
  }

  /**
   * @return {!Element}
   */
  _createShowMoreMessageElement() {
    const element = createElementWithClass('div', 'show-more-message');
    element.createChild('span');
    const showAllLink = element.createChild('span', 'link');
    showAllLink.textContent = Common.UIString('Show more');
    showAllLink.addEventListener('click', () => {
      this._maxAsyncStackChainDepth += Sources.CallStackSidebarPane._defaultMaxAsyncStackChainDepth;
      this._update();
    }, false);
    return element;
  }

  /**
   * @param {!Event} event
   */
  _onContextMenu(event) {
    const item = this._list.itemForNode(/** @type {?Node} */ (event.target));
    if (!item) {
      return;
    }
    const contextMenu = new UI.ContextMenu(event);
    const debuggerCallFrame = item[Sources.CallStackSidebarPane._debuggerCallFrameSymbol];
    if (debuggerCallFrame) {
      contextMenu.defaultSection().appendItem(Common.UIString('Restart frame'), () => debuggerCallFrame.restart());
    }
    contextMenu.defaultSection().appendItem(Common.UIString('Copy stack trace'), this._copyStackTrace.bind(this));
    if (item.uiLocation) {
      this.appendBlackboxURLContextMenuItems(contextMenu, item.uiLocation.uiSourceCode);
    }
    contextMenu.show();
  }

  /**
   * @param {!Event} event
   */
  _onClick(event) {
    const item = this._list.itemForNode(/** @type {?Node} */ (event.target));
    if (item) {
      this._activateItem(item);
    }
  }

  /**
   * @param {!Sources.CallStackSidebarPane.Item} item
   */
  _activateItem(item) {
    const uiLocation = item.uiLocation;
    if (this._muteActivateItem || !uiLocation) {
      return;
    }
    const debuggerCallFrame = item[Sources.CallStackSidebarPane._debuggerCallFrameSymbol];
    if (debuggerCallFrame && UI.context.flavor(SDK.DebuggerModel.CallFrame) !== debuggerCallFrame) {
      debuggerCallFrame.debuggerModel.setSelectedCallFrame(debuggerCallFrame);
      UI.context.setFlavor(SDK.DebuggerModel.CallFrame, debuggerCallFrame);
    } else {
      Common.Revealer.reveal(uiLocation);
    }
  }

  /**
   * @param {!UI.ContextMenu} contextMenu
   * @param {!Workspace.UISourceCode} uiSourceCode
   */
  appendBlackboxURLContextMenuItems(contextMenu, uiSourceCode) {
    const binding = Persistence.persistence.binding(uiSourceCode);
    if (binding) {
      uiSourceCode = binding.network;
    }
    if (uiSourceCode.project().type() === Workspace.projectTypes.FileSystem) {
      return;
    }
    const canBlackbox = Bindings.blackboxManager.canBlackboxUISourceCode(uiSourceCode);
    const isBlackboxed = Bindings.blackboxManager.isBlackboxedUISourceCode(uiSourceCode);
    const isContentScript = uiSourceCode.project().type() === Workspace.projectTypes.ContentScripts;

    const manager = Bindings.blackboxManager;
    if (canBlackbox) {
      if (isBlackboxed) {
        contextMenu.defaultSection().appendItem(
            Common.UIString('Stop blackboxing'), manager.unblackboxUISourceCode.bind(manager, uiSourceCode));
      } else {
        contextMenu.defaultSection().appendItem(
            Common.UIString('Blackbox script'), manager.blackboxUISourceCode.bind(manager, uiSourceCode));
      }
    }
    if (isContentScript) {
      if (isBlackboxed) {
        contextMenu.defaultSection().appendItem(
            Common.UIString('Stop blackboxing all content scripts'), manager.blackboxContentScripts.bind(manager));
      } else {
        contextMenu.defaultSection().appendItem(
            Common.UIString('Blackbox all content scripts'), manager.unblackboxContentScripts.bind(manager));
      }
    }
  }

  /**
   * @return {boolean}
   */
  _selectNextCallFrameOnStack() {
    return this._list.selectNextItem(false /* canWrap */, false /* center */);
  }

  /**
   * @return {boolean}
   */
  _selectPreviousCallFrameOnStack() {
    return this._list.selectPreviousItem(false /* canWrap */, false /* center */);
  }

  _copyStackTrace() {
    const text = [];
    for (const item of this._items) {
      let itemText = item.title;
      if (item.uiLocation) {
        itemText += ' (' + item.uiLocation.linkText(true /* skipTrim */) + ')';
      }
      text.push(itemText);
    }
    Host.InspectorFrontendHost.copyText(text.join('\n'));
  }
};

Sources.CallStackSidebarPane._debuggerCallFrameSymbol = Symbol('debuggerCallFrame');
Sources.CallStackSidebarPane._elementSymbol = Symbol('element');
Sources.CallStackSidebarPane._defaultMaxAsyncStackChainDepth = 32;

/**
 * @implements {UI.ActionDelegate}
 */
Sources.CallStackSidebarPane.ActionDelegate = class {
  /**
   * @override
   * @param {!UI.Context} context
   * @param {string} actionId
   * @return {boolean}
   */
  handleAction(context, actionId) {
    const callStackSidebarPane = self.runtime.sharedInstance(Sources.CallStackSidebarPane);
    switch (actionId) {
      case 'debugger.next-call-frame':
        callStackSidebarPane._selectNextCallFrameOnStack();
        return true;
      case 'debugger.previous-call-frame':
        callStackSidebarPane._selectPreviousCallFrameOnStack();
        return true;
    }
    return false;
  }
};

Sources.CallStackSidebarPane.Item = class {
  /**
   * @param {!SDK.DebuggerModel.CallFrame} frame
   * @param {!Bindings.LiveLocationPool} locationPool
   * @param {function(!Sources.CallStackSidebarPane.Item)} updateDelegate
   * @return {!Sources.CallStackSidebarPane.Item}
   */
  static createForDebuggerCallFrame(frame, locationPool, updateDelegate) {
    const item = new Sources.CallStackSidebarPane.Item(UI.beautifyFunctionName(frame.functionName), updateDelegate);
    Bindings.debuggerWorkspaceBinding.createCallFrameLiveLocation(
        frame.location(), item._update.bind(item), locationPool);
    return item;
  }

  /**
   * @param {string} title
   * @param {?SDK.DebuggerModel} debuggerModel
   * @param {!Array<!Protocol.Runtime.CallFrame>} frames
   * @param {!Bindings.LiveLocationPool} locationPool
   * @param {function(!Sources.CallStackSidebarPane.Item)} updateDelegate
   * @return {!Array<!Sources.CallStackSidebarPane.Item>}
   */
  static createItemsForAsyncStack(title, debuggerModel, frames, locationPool, updateDelegate) {
    const whiteboxedItemsSymbol = Symbol('whiteboxedItems');
    const asyncHeaderItem = new Sources.CallStackSidebarPane.Item(title, updateDelegate);
    asyncHeaderItem[whiteboxedItemsSymbol] = new Set();
    asyncHeaderItem.isAsyncHeader = true;

    const asyncFrameItems = frames.map(frame => {
      const item = new Sources.CallStackSidebarPane.Item(UI.beautifyFunctionName(frame.functionName), update);
      const rawLocation = debuggerModel ?
          debuggerModel.createRawLocationByScriptId(frame.scriptId, frame.lineNumber, frame.columnNumber) :
          null;
      if (!rawLocation) {
        item.linkText = (frame.url || '<unknown>') + ':' + (frame.lineNumber + 1);
        item.updateDelegate(item);
      } else {
        Bindings.debuggerWorkspaceBinding.createCallFrameLiveLocation(
            rawLocation, item._update.bind(item), locationPool);
      }
      return item;
    });

    updateDelegate(asyncHeaderItem);
    return [asyncHeaderItem, ...asyncFrameItems];

    /**
     * @param {!Sources.CallStackSidebarPane.Item} item
     */
    function update(item) {
      updateDelegate(item);
      let shouldUpdate = false;
      const items = asyncHeaderItem[whiteboxedItemsSymbol];
      if (item.isBlackboxed) {
        items.delete(item);
        shouldUpdate = items.size === 0;
      } else {
        shouldUpdate = items.size === 0;
        items.add(item);
      }
      asyncHeaderItem.isBlackboxed = asyncHeaderItem[whiteboxedItemsSymbol].size === 0;
      if (shouldUpdate) {
        updateDelegate(asyncHeaderItem);
      }
    }
  }

  /**
   * @param {string} title
   * @param {function(!Sources.CallStackSidebarPane.Item)} updateDelegate
   */
  constructor(title, updateDelegate) {
    this.isBlackboxed = false;
    this.title = title;
    this.linkText = '';
    this.uiLocation = null;
    this.isAsyncHeader = false;
    this.updateDelegate = updateDelegate;
  }

  /**
   * @param {!Bindings.LiveLocation} liveLocation
   */
  _update(liveLocation) {
    const uiLocation = liveLocation.uiLocation();
    this.isBlackboxed = uiLocation ? Bindings.blackboxManager.isBlackboxedUISourceCode(uiLocation.uiSourceCode) : false;
    this.linkText = uiLocation ? uiLocation.linkText() : '';
    this.uiLocation = uiLocation;
    this.updateDelegate(this);
  }
};
