/*
 * Copyright (C) 2007, 2008 Apple Inc.  All rights reserved.
 * Copyright (C) IBM Corp. 2009  All rights reserved.
 * Copyright (C) 2010 Google 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.
 * 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.
 */

Network.RequestHeadersView = class extends UI.VBox {
  /**
   * @param {!SDK.NetworkRequest} request
   */
  constructor(request) {
    super();
    this.registerRequiredCSS('network/requestHeadersView.css');
    this.element.classList.add('request-headers-view');

    this._request = request;
    this._decodeRequestParameters = true;
    this._showRequestHeadersText = false;
    this._showResponseHeadersText = false;

    /** @type {?UI.TreeElement} */
    this._highlightedElement = null;

    const root = new UI.TreeOutlineInShadow();
    root.registerRequiredCSS('network/requestHeadersTree.css');
    root.element.classList.add('request-headers-tree');
    root.setFocusable(false);
    root.makeDense();
    root.expandTreeElementsWhenArrowing = true;
    this.element.appendChild(root.element);

    const generalCategory = new Network.RequestHeadersView.Category(root, 'general', Common.UIString('General'));
    generalCategory.hidden = false;
    this._urlItem = generalCategory.createLeaf();
    this._requestMethodItem = generalCategory.createLeaf();
    this._statusCodeItem = generalCategory.createLeaf();
    this._remoteAddressItem = generalCategory.createLeaf();
    this._remoteAddressItem.hidden = true;
    this._referrerPolicyItem = generalCategory.createLeaf();
    this._referrerPolicyItem.hidden = true;

    this._responseHeadersCategory = new Network.RequestHeadersView.Category(root, 'responseHeaders', '');
    this._requestHeadersCategory = new Network.RequestHeadersView.Category(root, 'requestHeaders', '');
    this._queryStringCategory = new Network.RequestHeadersView.Category(root, 'queryString', '');
    this._formDataCategory = new Network.RequestHeadersView.Category(root, 'formData', '');
    this._requestPayloadCategory =
        new Network.RequestHeadersView.Category(root, 'requestPayload', Common.UIString('Request Payload'));
  }

  /**
   * @override
   */
  wasShown() {
    this._clearHighlight();
    this._request.addEventListener(SDK.NetworkRequest.Events.RemoteAddressChanged, this._refreshRemoteAddress, this);
    this._request.addEventListener(SDK.NetworkRequest.Events.RequestHeadersChanged, this._refreshRequestHeaders, this);
    this._request.addEventListener(
        SDK.NetworkRequest.Events.ResponseHeadersChanged, this._refreshResponseHeaders, this);
    this._request.addEventListener(SDK.NetworkRequest.Events.FinishedLoading, this._refreshHTTPInformation, this);

    this._refreshURL();
    this._refreshQueryString();
    this._refreshRequestHeaders();
    this._refreshResponseHeaders();
    this._refreshHTTPInformation();
    this._refreshRemoteAddress();
    this._refreshReferrerPolicy();
  }

  /**
   * @override
   */
  willHide() {
    this._request.removeEventListener(SDK.NetworkRequest.Events.RemoteAddressChanged, this._refreshRemoteAddress, this);
    this._request.removeEventListener(
        SDK.NetworkRequest.Events.RequestHeadersChanged, this._refreshRequestHeaders, this);
    this._request.removeEventListener(
        SDK.NetworkRequest.Events.ResponseHeadersChanged, this._refreshResponseHeaders, this);
    this._request.removeEventListener(SDK.NetworkRequest.Events.FinishedLoading, this._refreshHTTPInformation, this);
  }

  /**
   * @param {string} name
   * @param {string} value
   * @return {!DocumentFragment}
   */
  _formatHeader(name, value) {
    const fragment = createDocumentFragment();
    fragment.createChild('div', 'header-name').textContent = name + ': ';
    fragment.createChild('span', 'header-separator');
    fragment.createChild('div', 'header-value source-code').textContent = value;

    return fragment;
  }

  /**
   * @param {string} value
   * @param {string} className
   * @param {boolean} decodeParameters
   * @return {!Element}
   */
  _formatParameter(value, className, decodeParameters) {
    let errorDecoding = false;

    if (decodeParameters) {
      value = value.replace(/\+/g, ' ');
      if (value.indexOf('%') >= 0) {
        try {
          value = decodeURIComponent(value);
        } catch (e) {
          errorDecoding = true;
        }
      }
    }
    const div = createElementWithClass('div', className);
    if (value === '')
      div.classList.add('empty-value');
    if (errorDecoding)
      div.createChild('span', 'header-decode-error').textContent = Common.UIString('(unable to decode value)');
    else
      div.textContent = value;
    return div;
  }

  _refreshURL() {
    this._urlItem.title = this._formatHeader(Common.UIString('Request URL'), this._request.url());
  }

  _refreshQueryString() {
    const queryString = this._request.queryString();
    const queryParameters = this._request.queryParameters;
    this._queryStringCategory.hidden = !queryParameters;
    if (queryParameters) {
      this._refreshParams(
          Common.UIString('Query String Parameters'), queryParameters, queryString, this._queryStringCategory);
    }
  }

  async _refreshFormData() {
    this._formDataCategory.hidden = true;
    this._requestPayloadCategory.hidden = true;

    const formData = await this._request.requestFormData();
    if (!formData)
      return;

    const formParameters = await this._request.formParameters();
    if (formParameters) {
      this._formDataCategory.hidden = false;
      this._refreshParams(Common.UIString('Form Data'), formParameters, formData, this._formDataCategory);
    } else {
      this._requestPayloadCategory.hidden = false;
      try {
        const json = JSON.parse(formData);
        this._refreshRequestJSONPayload(json, formData);
      } catch (e) {
        this._populateTreeElementWithSourceText(this._requestPayloadCategory, formData);
      }
    }
  }

  /**
   * @param {!UI.TreeElement} treeElement
   * @param {?string} sourceText
   */
  _populateTreeElementWithSourceText(treeElement, sourceText) {
    const max_len = 3000;
    const text = (sourceText || '').trim();
    const trim = text.length > max_len;

    const sourceTextElement = createElementWithClass('span', 'header-value source-code');
    sourceTextElement.textContent = trim ? text.substr(0, max_len) : text;

    const sourceTreeElement = new UI.TreeElement(sourceTextElement);
    sourceTreeElement.selectable = false;
    treeElement.removeChildren();
    treeElement.appendChild(sourceTreeElement);
    if (!trim)
      return;

    const showMoreButton = createElementWithClass('button', 'request-headers-show-more-button');
    showMoreButton.textContent = Common.UIString('Show more');
    showMoreButton.addEventListener('click', () => {
      showMoreButton.remove();
      sourceTextElement.textContent = text;
    });
    sourceTextElement.appendChild(showMoreButton);
  }

  /**
   * @param {string} title
   * @param {?Array.<!SDK.NetworkRequest.NameValue>} params
   * @param {?string} sourceText
   * @param {!UI.TreeElement} paramsTreeElement
   */
  _refreshParams(title, params, sourceText, paramsTreeElement) {
    paramsTreeElement.removeChildren();

    paramsTreeElement.listItemElement.removeChildren();
    paramsTreeElement.listItemElement.createTextChild(title);

    const headerCount = createElementWithClass('span', 'header-count');
    headerCount.textContent = Common.UIString('\u00A0(%d)', params.length);
    paramsTreeElement.listItemElement.appendChild(headerCount);

    /**
     * @param {!Event} event
     * @this {Network.RequestHeadersView}
     */
    function toggleViewSource(event) {
      paramsTreeElement[Network.RequestHeadersView._viewSourceSymbol] =
          !paramsTreeElement[Network.RequestHeadersView._viewSourceSymbol];
      this._refreshParams(title, params, sourceText, paramsTreeElement);
      event.consume();
    }

    paramsTreeElement.listItemElement.appendChild(this._createViewSourceToggle(
        paramsTreeElement[Network.RequestHeadersView._viewSourceSymbol], toggleViewSource.bind(this)));

    if (paramsTreeElement[Network.RequestHeadersView._viewSourceSymbol]) {
      this._populateTreeElementWithSourceText(paramsTreeElement, sourceText);
      return;
    }

    const toggleTitle =
        this._decodeRequestParameters ? Common.UIString('view URL encoded') : Common.UIString('view decoded');
    const toggleButton = this._createToggleButton(toggleTitle);
    toggleButton.addEventListener('click', this._toggleURLDecoding.bind(this), false);
    paramsTreeElement.listItemElement.appendChild(toggleButton);

    for (let i = 0; i < params.length; ++i) {
      const paramNameValue = createDocumentFragment();
      if (params[i].name !== '') {
        const name = this._formatParameter(params[i].name + ': ', 'header-name', this._decodeRequestParameters);
        const value = this._formatParameter(params[i].value, 'header-value source-code', this._decodeRequestParameters);
        paramNameValue.appendChild(name);
        paramNameValue.createChild('span', 'header-separator');
        paramNameValue.appendChild(value);
      } else {
        paramNameValue.appendChild(
            this._formatParameter(Common.UIString('(empty)'), 'empty-request-header', this._decodeRequestParameters));
      }

      const paramTreeElement = new UI.TreeElement(paramNameValue);
      paramTreeElement.selectable = false;
      paramsTreeElement.appendChild(paramTreeElement);
    }
  }

  /**
   * @param {*} parsedObject
   * @param {string} sourceText
   */
  _refreshRequestJSONPayload(parsedObject, sourceText) {
    const treeElement = this._requestPayloadCategory;
    treeElement.removeChildren();

    const listItem = this._requestPayloadCategory.listItemElement;
    listItem.removeChildren();
    listItem.createTextChild(this._requestPayloadCategory.title);

    /**
     * @param {!Event} event
     * @this {Network.RequestHeadersView}
     */
    function toggleViewSource(event) {
      treeElement[Network.RequestHeadersView._viewSourceSymbol] =
          !treeElement[Network.RequestHeadersView._viewSourceSymbol];
      this._refreshRequestJSONPayload(parsedObject, sourceText);
      event.consume();
    }

    listItem.appendChild(this._createViewSourceToggle(
        treeElement[Network.RequestHeadersView._viewSourceSymbol], toggleViewSource.bind(this)));
    if (treeElement[Network.RequestHeadersView._viewSourceSymbol]) {
      this._populateTreeElementWithSourceText(this._requestPayloadCategory, sourceText);
    } else {
      const object = SDK.RemoteObject.fromLocalObject(parsedObject);
      const section = new ObjectUI.ObjectPropertiesSection(object, object.description);
      section.expand();
      section.editable = false;
      treeElement.appendChild(new UI.TreeElement(section.element));
    }
  }

  /**
   * @param {boolean} viewSource
   * @param {function(!Event)} handler
   * @return {!Element}
   */
  _createViewSourceToggle(viewSource, handler) {
    const viewSourceToggleTitle = viewSource ? Common.UIString('view parsed') : Common.UIString('view source');
    const viewSourceToggleButton = this._createToggleButton(viewSourceToggleTitle);
    viewSourceToggleButton.addEventListener('click', handler, false);
    return viewSourceToggleButton;
  }

  /**
   * @param {!Event} event
   */
  _toggleURLDecoding(event) {
    this._decodeRequestParameters = !this._decodeRequestParameters;
    this._refreshQueryString();
    this._refreshFormData();
    event.consume();
  }

  _refreshRequestHeaders() {
    const treeElement = this._requestHeadersCategory;
    const headers = this._request.requestHeaders().slice();
    headers.sort(function(a, b) {
      return a.name.toLowerCase().compareTo(b.name.toLowerCase());
    });
    const headersText = this._request.requestHeadersText();

    if (this._showRequestHeadersText && headersText)
      this._refreshHeadersText(Common.UIString('Request Headers'), headers.length, headersText, treeElement);
    else
      this._refreshHeaders(Common.UIString('Request Headers'), headers, treeElement, headersText === undefined);

    if (headersText) {
      const toggleButton = this._createHeadersToggleButton(this._showRequestHeadersText);
      toggleButton.addEventListener('click', this._toggleRequestHeadersText.bind(this), false);
      treeElement.listItemElement.appendChild(toggleButton);
    }

    this._refreshFormData();
  }

  _refreshResponseHeaders() {
    const treeElement = this._responseHeadersCategory;
    const headers = this._request.sortedResponseHeaders.slice();
    const headersText = this._request.responseHeadersText;

    if (this._showResponseHeadersText)
      this._refreshHeadersText(Common.UIString('Response Headers'), headers.length, headersText, treeElement);
    else
      this._refreshHeaders(Common.UIString('Response Headers'), headers, treeElement);

    if (headersText) {
      const toggleButton = this._createHeadersToggleButton(this._showResponseHeadersText);
      toggleButton.addEventListener('click', this._toggleResponseHeadersText.bind(this), false);
      treeElement.listItemElement.appendChild(toggleButton);
    }
  }

  _refreshHTTPInformation() {
    const requestMethodElement = this._requestMethodItem;
    requestMethodElement.hidden = !this._request.statusCode;
    const statusCodeElement = this._statusCodeItem;
    statusCodeElement.hidden = !this._request.statusCode;

    if (this._request.statusCode) {
      const statusCodeFragment = createDocumentFragment();
      statusCodeFragment.createChild('div', 'header-name').textContent = Common.UIString('Status Code') + ': ';
      statusCodeFragment.createChild('span', 'header-separator');

      const statusCodeImage = statusCodeFragment.createChild('span', 'resource-status-image', 'dt-icon-label');
      statusCodeImage.title = this._request.statusCode + ' ' + this._request.statusText;

      if (this._request.statusCode < 300 || this._request.statusCode === 304)
        statusCodeImage.type = 'smallicon-green-ball';
      else if (this._request.statusCode < 400)
        statusCodeImage.type = 'smallicon-orange-ball';
      else
        statusCodeImage.type = 'smallicon-red-ball';

      requestMethodElement.title = this._formatHeader(Common.UIString('Request Method'), this._request.requestMethod);

      const statusTextElement = statusCodeFragment.createChild('div', 'header-value source-code');
      let statusText = this._request.statusCode + ' ' + this._request.statusText;
      if (this._request.fetchedViaServiceWorker) {
        statusText += ' ' + Common.UIString('(from ServiceWorker)');
        statusTextElement.classList.add('status-from-cache');
      } else if (this._request.redirectSource() && this._request.redirectSource().signedExchangeInfo()) {
        statusText += ' ' + Common.UIString('(from signed-exchange)');
        statusTextElement.classList.add('status-from-cache');
      } else if (this._request.cached()) {
        if (this._request.cachedInMemory())
          statusText += ' ' + Common.UIString('(from memory cache)');
        else
          statusText += ' ' + Common.UIString('(from disk cache)');
        statusTextElement.classList.add('status-from-cache');
      }
      statusTextElement.textContent = statusText;

      statusCodeElement.title = statusCodeFragment;
    }
  }

  /**
   * @param {string} title
   * @param {!UI.TreeElement} headersTreeElement
   * @param {number} headersLength
   */
  _refreshHeadersTitle(title, headersTreeElement, headersLength) {
    headersTreeElement.listItemElement.removeChildren();
    headersTreeElement.listItemElement.createTextChild(title);

    const headerCount = Common.UIString('\u00A0(%d)', headersLength);
    headersTreeElement.listItemElement.createChild('span', 'header-count').textContent = headerCount;
  }

  /**
   * @param {string} title
   * @param {!Array.<!SDK.NetworkRequest.NameValue>} headers
   * @param {!UI.TreeElement} headersTreeElement
   * @param {boolean=} provisionalHeaders
   */
  _refreshHeaders(title, headers, headersTreeElement, provisionalHeaders) {
    headersTreeElement.removeChildren();

    const length = headers.length;
    this._refreshHeadersTitle(title, headersTreeElement, length);

    if (provisionalHeaders) {
      const cautionText = Common.UIString('Provisional headers are shown');
      const cautionFragment = createDocumentFragment();
      cautionFragment.createChild('span', '', 'dt-icon-label').type = 'smallicon-warning';
      cautionFragment.createChild('div', 'caution').textContent = cautionText;
      const cautionTreeElement = new UI.TreeElement(cautionFragment);
      cautionTreeElement.selectable = false;
      headersTreeElement.appendChild(cautionTreeElement);
    }

    headersTreeElement.hidden = !length && !provisionalHeaders;
    for (let i = 0; i < length; ++i) {
      const headerTreeElement = new UI.TreeElement(this._formatHeader(headers[i].name, headers[i].value));
      headerTreeElement.selectable = false;
      headersTreeElement.appendChild(headerTreeElement);
      headerTreeElement[Network.RequestHeadersView._headerNameSymbol] = headers[i].name;
    }
  }

  /**
   * @param {string} title
   * @param {number} count
   * @param {string} headersText
   * @param {!UI.TreeElement} headersTreeElement
   */
  _refreshHeadersText(title, count, headersText, headersTreeElement) {
    this._populateTreeElementWithSourceText(headersTreeElement, headersText);
    this._refreshHeadersTitle(title, headersTreeElement, count);
  }

  _refreshRemoteAddress() {
    const remoteAddress = this._request.remoteAddress();
    const treeElement = this._remoteAddressItem;
    treeElement.hidden = !remoteAddress;
    if (remoteAddress)
      treeElement.title = this._formatHeader(Common.UIString('Remote Address'), remoteAddress);
  }

  _refreshReferrerPolicy() {
    const referrerPolicy = this._request.referrerPolicy();
    const treeElement = this._referrerPolicyItem;
    treeElement.hidden = !referrerPolicy;
    if (referrerPolicy)
      treeElement.title = this._formatHeader(Common.UIString('Referrer Policy'), referrerPolicy);
  }

  /**
   * @param {!Event} event
   */
  _toggleRequestHeadersText(event) {
    this._showRequestHeadersText = !this._showRequestHeadersText;
    this._refreshRequestHeaders();
    event.consume();
  }

  /**
   * @param {!Event} event
   */
  _toggleResponseHeadersText(event) {
    this._showResponseHeadersText = !this._showResponseHeadersText;
    this._refreshResponseHeaders();
    event.consume();
  }

  /**
   * @param {string} title
   * @return {!Element}
   */
  _createToggleButton(title) {
    const button = createElementWithClass('span', 'header-toggle');
    button.textContent = title;
    return button;
  }

  /**
   * @param {boolean} isHeadersTextShown
   * @return {!Element}
   */
  _createHeadersToggleButton(isHeadersTextShown) {
    const toggleTitle = isHeadersTextShown ? Common.UIString('view parsed') : Common.UIString('view source');
    return this._createToggleButton(toggleTitle);
  }

  _clearHighlight() {
    if (this._highlightedElement)
      this._highlightedElement.listItemElement.classList.remove('header-highlight');
    this._highlightedElement = null;
  }


  /**
   * @param {?UI.TreeElement} category
   * @param {string} name
   */
  _revealAndHighlight(category, name) {
    this._clearHighlight();
    for (const element of category.children()) {
      if (element[Network.RequestHeadersView._headerNameSymbol] !== name)
        continue;
      this._highlightedElement = element;
      element.reveal();
      element.listItemElement.classList.add('header-highlight');
      return;
    }
  }

  /**
   * @param {string} header
   */
  revealRequestHeader(header) {
    this._revealAndHighlight(this._requestHeadersCategory, header);
  }

  /**
   * @param {string} header
   */
  revealResponseHeader(header) {
    this._revealAndHighlight(this._responseHeadersCategory, header);
  }
};

Network.RequestHeadersView._headerNameSymbol = Symbol('HeaderName');
Network.RequestHeadersView._viewSourceSymbol = Symbol('ViewSource');

/**
 * @unrestricted
 */
Network.RequestHeadersView.Category = class extends UI.TreeElement {
  /**
   * @param {!UI.TreeOutline} root
   * @param {string} name
   * @param {string=} title
   */
  constructor(root, name, title) {
    super(title || '', true);
    this.selectable = false;
    this.toggleOnClick = true;
    this.hidden = true;
    this._expandedSetting = Common.settings.createSetting('request-info-' + name + '-category-expanded', true);
    this.expanded = this._expandedSetting.get();
    root.appendChild(this);
  }

  /**
   * @return {!UI.TreeElement}
   */
  createLeaf() {
    const leaf = new UI.TreeElement();
    leaf.selectable = false;
    this.appendChild(leaf);
    return leaf;
  }

  /**
   * @override
   */
  onexpand() {
    this._expandedSetting.set(true);
  }

  /**
   * @override
   */
  oncollapse() {
    this._expandedSetting.set(false);
  }
};
