/*
 * Copyright (C) 2011 Google Inc.  All rights reserved.
 * Copyright (C) 2007, 2008 Apple Inc.  All rights reserved.
 * Copyright (C) 2008 Matt Lilek <webkit@mattlilek.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.
 */

/**
 * @param {?SDK.Target} target
 * @param {!Components.Linkifier} linkifier
 * @param {!Protocol.Runtime.StackTrace=} stackTrace
 * @param {function()=} contentUpdated
 * @return {{element: !Element, links: !Array<!Element>}}
 */
export function buildStackTracePreviewContents(target, linkifier, stackTrace, contentUpdated) {
  const element = createElementWithClass('span', 'monospace');
  element.style.display = 'inline-block';
  const shadowRoot = UI.createShadowRootWithCoreStyles(element, 'components/jsUtils.css');
  const contentElement = shadowRoot.createChild('table', 'stack-preview-container');
  let totalHiddenCallFramesCount = 0;
  let totalCallFramesCount = 0;
  /** @type {!Array<!Element>} */
  const links = [];

  /**
   * @param {!Protocol.Runtime.StackTrace} stackTrace
   * @return {boolean}
   */
  function appendStackTrace(stackTrace) {
    let hiddenCallFrames = 0;
    for (const stackFrame of stackTrace.callFrames) {
      totalCallFramesCount++;
      let shouldHide = totalCallFramesCount > 30 && stackTrace.callFrames.length > 31;
      const row = createElement('tr');
      row.createChild('td').textContent = '\n';
      row.createChild('td', 'function-name').textContent = UI.beautifyFunctionName(stackFrame.functionName);
      const link = linkifier.maybeLinkifyConsoleCallFrame(target, stackFrame);
      if (link) {
        link.addEventListener('contextmenu', populateContextMenu.bind(null, link));
        const uiLocation = Components.Linkifier.uiLocation(link);
        if (uiLocation && Bindings.blackboxManager.isBlackboxedUISourceCode(uiLocation.uiSourceCode)) {
          shouldHide = true;
        }
        row.createChild('td').textContent = ' @ ';
        row.createChild('td').appendChild(link);
        links.push(link);
      }
      if (shouldHide) {
        row.classList.add('blackboxed');
        ++hiddenCallFrames;
      }
      contentElement.appendChild(row);
    }
    totalHiddenCallFramesCount += hiddenCallFrames;
    return stackTrace.callFrames.length === hiddenCallFrames;
  }

  /**
   * @param {!Element} link
   * @param {!Event} event
   */
  function populateContextMenu(link, event) {
    const contextMenu = new UI.ContextMenu(event);
    event.consume(true);
    const uiLocation = Components.Linkifier.uiLocation(link);
    if (uiLocation && Bindings.blackboxManager.canBlackboxUISourceCode(uiLocation.uiSourceCode)) {
      if (Bindings.blackboxManager.isBlackboxedUISourceCode(uiLocation.uiSourceCode)) {
        contextMenu.debugSection().appendItem(
            ls`Stop blackboxing`, () => Bindings.blackboxManager.unblackboxUISourceCode(uiLocation.uiSourceCode));
      } else {
        contextMenu.debugSection().appendItem(
            ls`Blackbox script`, () => Bindings.blackboxManager.blackboxUISourceCode(uiLocation.uiSourceCode));
      }
    }
    contextMenu.appendApplicableItems(event);
    contextMenu.show();
  }

  if (!stackTrace) {
    return {element, links};
  }

  appendStackTrace(stackTrace);

  let asyncStackTrace = stackTrace.parent;
  while (asyncStackTrace) {
    if (!asyncStackTrace.callFrames.length) {
      asyncStackTrace = asyncStackTrace.parent;
      continue;
    }
    const row = contentElement.createChild('tr');
    row.createChild('td').textContent = '\n';
    row.createChild('td', 'stack-preview-async-description').textContent =
        UI.asyncStackTraceLabel(asyncStackTrace.description);
    row.createChild('td');
    row.createChild('td');
    if (appendStackTrace(asyncStackTrace)) {
      row.classList.add('blackboxed');
    }
    asyncStackTrace = asyncStackTrace.parent;
  }

  if (totalHiddenCallFramesCount) {
    const row = contentElement.createChild('tr', 'show-blackboxed-link');
    row.createChild('td').textContent = '\n';
    const cell = row.createChild('td');
    cell.colSpan = 4;
    const showAllLink = cell.createChild('span', 'link');
    if (totalHiddenCallFramesCount === 1) {
      showAllLink.textContent = ls`Show 1 more frame`;
    } else {
      showAllLink.textContent = ls`Show ${totalHiddenCallFramesCount} more frames`;
    }
    showAllLink.addEventListener('click', () => {
      contentElement.classList.add('show-blackboxed');
      if (contentUpdated) {
        contentUpdated();
      }
    }, false);
  }

  return {element, links};
}

/* Legacy exported object */
self.Components = self.Components || {};

/* Legacy exported object */
Components = Components || {};

Components.JSPresentationUtils = {};

Components.JSPresentationUtils.buildStackTracePreviewContents = buildStackTracePreviewContents;
