/*
 * Copyright (C) 2017 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. 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 INC. 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.
 */

WI.ResourceHeadersContentView = class ResourceHeadersContentView extends WI.ContentView
{
    constructor(resource, delegate)
    {
        super(null);

        console.assert(resource instanceof WI.Resource);
        console.assert(delegate);

        this._resource = resource;
        this._resource.addEventListener(WI.Resource.Event.MetricsDidChange, this._resourceMetricsDidChange, this);
        this._resource.addEventListener(WI.Resource.Event.RequestHeadersDidChange, this._resourceRequestHeadersDidChange, this);
        this._resource.addEventListener(WI.Resource.Event.ResponseReceived, this._resourceResponseReceived, this);

        this._delegate = delegate;

        this._searchQuery = null;
        this._searchResults = null;
        this._searchDOMChanges = [];
        this._searchIndex = -1;
        this._automaticallyRevealFirstSearchResult = false;
        this._bouncyHighlightElement = null;
        this._popover = null;
        this._popoverCallStackIconElement = null;

        this._redirectDetailsSections = [];

        this.element.classList.add("resource-details", "resource-headers");
        this.element.tabIndex = 0;

        this._needsSummaryRefresh = false;
        this._needsRedirectHeadersRefresh = false;
        this._needsRequestHeadersRefresh = false;
        this._needsResponseHeadersRefresh = false;
    }

    // Protected

    initialLayout()
    {
        super.initialLayout();

        this._summarySection = new WI.ResourceDetailsSection(WI.UIString("Summary"), "summary");
        this.element.appendChild(this._summarySection.element);
        this._refreshSummarySection();

        this._refreshRedirectHeadersSections();

        this._requestHeadersSection = new WI.ResourceDetailsSection(WI.UIString("Request"), "headers");
        this.element.appendChild(this._requestHeadersSection.element);
        this._refreshRequestHeadersSection();

        this._responseHeadersSection = new WI.ResourceDetailsSection(WI.UIString("Response"), "headers");
        this.element.appendChild(this._responseHeadersSection.element);
        this._refreshResponseHeadersSection();

        if (this._resource.urlComponents.queryString) {
            this._queryStringSection = new WI.ResourceDetailsSection(WI.UIString("Query String Parameters"));
            this.element.appendChild(this._queryStringSection.element);
            this._refreshQueryStringSection();
        }

        if (this._resource.requestData) {
            this._requestDataSection = new WI.ResourceDetailsSection(WI.UIString("Request Data"));
            this.element.appendChild(this._requestDataSection.element);
            this._refreshRequestDataSection();
        }

        this._needsSummaryRefresh = false;
        this._needsRedirectHeadersRefresh = false;
        this._needsRequestHeadersRefresh = false;
        this._needsResponseHeadersRefresh = false;
    }

    layout()
    {
        super.layout();

        if (this._needsSummaryRefresh) {
            this._refreshSummarySection();
            this._needsSummaryRefresh = false;
        }

        if (this._needsRedirectHeadersRefresh) {
            this._refreshRedirectHeadersSections();
            this._needsRedirectHeadersRefresh = false;
        }

        if (this._needsRequestHeadersRefresh) {
            this._refreshRequestHeadersSection();
            this._needsRequestHeadersRefresh = false;
        }

        if (this._needsResponseHeadersRefresh) {
            this._refreshResponseHeadersSection();
            this._needsResponseHeadersRefresh = false;
        }
    }

    hidden()
    {
        super.hidden();

        if (this._popover)
            this._popover.dismiss();
    }

    closed()
    {
        this._resource.removeEventListener(null, null, this);

        super.closed();
    }

    get supportsSearch()
    {
        return true;
    }

    get numberOfSearchResults()
    {
        return this._searchResults ? this._searchResults.length : null;
    }

    get hasPerformedSearch()
    {
        return this._searchResults !== null;
    }

    set automaticallyRevealFirstSearchResult(reveal)
    {
        this._automaticallyRevealFirstSearchResult = reveal;

        // If we haven't shown a search result yet, reveal one now.
        if (this._automaticallyRevealFirstSearchResult && this.numberOfSearchResults > 0) {
            if (this._searchIndex === -1)
                this.revealNextSearchResult();
        }
    }

    performSearch(query)
    {
        if (query === this._searchQuery)
            return;

        WI.revertDOMChanges(this._searchDOMChanges);

        this._searchQuery = query;
        this._searchResults = [];
        this._searchDOMChanges = [];
        this._searchIndex = -1;

        this._perfomSearchOnKeyValuePairs();

        this.dispatchEventToListeners(WI.ContentView.Event.NumberOfSearchResultsDidChange);

        if (this._automaticallyRevealFirstSearchResult && this._searchResults.length > 0)
            this.revealNextSearchResult();
    }

    searchCleared()
    {
        WI.revertDOMChanges(this._searchDOMChanges);

        this._searchQuery = null;
        this._searchResults = null;
        this._searchDOMChanges = [];
        this._searchIndex = -1;
    }

    revealPreviousSearchResult(changeFocus)
    {
        if (!this.numberOfSearchResults)
            return;

        if (this._searchIndex > 0)
            --this._searchIndex;
        else
            this._searchIndex = this._searchResults.length - 1;

        this._revealSearchResult(this._searchIndex, changeFocus);
    }

    revealNextSearchResult(changeFocus)
    {
        if (!this.numberOfSearchResults)
            return;

        if (this._searchIndex + 1 < this._searchResults.length)
            ++this._searchIndex;
        else
            this._searchIndex = 0;

        this._revealSearchResult(this._searchIndex, changeFocus);
    }

    // Private

    _responseSourceDisplayString(responseSource)
    {
        switch (responseSource) {
        case WI.Resource.ResponseSource.Network:
            return WI.UIString("Network");
        case WI.Resource.ResponseSource.MemoryCache:
            return WI.UIString("Memory Cache");
        case WI.Resource.ResponseSource.DiskCache:
            return WI.UIString("Disk Cache");
        case WI.Resource.ResponseSource.ServiceWorker:
            return WI.UIString("Service Worker");
        case WI.Resource.ResponseSource.Unknown:
        default:
            return null;
        }
    }

    _refreshSummarySection()
    {
        let detailsElement = this._summarySection.detailsElement;
        detailsElement.removeChildren();

        this._summarySection.toggleError(this._resource.hadLoadingError());

        for (let redirect of this._resource.redirects)
            this._summarySection.appendKeyValuePair(WI.UIString("URL"), redirect.url.insertWordBreakCharacters(), "url");
        this._summarySection.appendKeyValuePair(WI.UIString("URL"), this._resource.url.insertWordBreakCharacters(), "url");

        let status = emDash;
        if (!isNaN(this._resource.statusCode))
            status = this._resource.statusCode + (this._resource.statusText ? " " + this._resource.statusText : "");
        this._summarySection.appendKeyValuePair(WI.UIString("Status"), status);

        // FIXME: <https://webkit.org/b/178827> Web Inspector: Should be able to link directly to the ServiceWorker that handled a particular load

        let source = this._responseSourceDisplayString(this._resource.responseSource) || emDash;
        this._summarySection.appendKeyValuePair(WI.UIString("Source"), source);

        if (this._resource.remoteAddress)
            this._summarySection.appendKeyValuePair(WI.UIString("Address"), this._resource.remoteAddress);

        let initiatorLocation = this._resource.initiatorSourceCodeLocation;
        if (initiatorLocation) {

            let fragment = document.createDocumentFragment();

            const options = {
                dontFloat: true,
                ignoreSearchTab: true,
                ignoreNetworkTab: true,
            };
            let link = WI.createSourceCodeLocationLink(initiatorLocation, options);
            fragment.appendChild(link);

            let callFrames = this._resource.initiatorCallFrames;
            if (callFrames) {
                this._popoverCallStackIconElement = document.createElement("img");
                this._popoverCallStackIconElement.className = "call-stack";
                fragment.appendChild(this._popoverCallStackIconElement);

                this._popoverCallStackIconElement.addEventListener("click", (event) => {
                    if (!this._popover) {
                        this._popover = new WI.Popover(this);
                        this._popover.windowResizeHandler = () => { this._presentPopoverBelowCallStackElement(); };
                    }

                    const selectable = false;
                    let callFramesTreeOutline = new WI.TreeOutline(selectable);
                    callFramesTreeOutline.disclosureButtons = false;
                    let callFrameTreeController = new WI.CallFrameTreeController(callFramesTreeOutline);
                    callFrameTreeController.callFrames = callFrames;

                    let popoverContent = document.createElement("div");
                    popoverContent.appendChild(callFrameTreeController.treeOutline.element);
                    this._popover.content = popoverContent;

                    this._presentPopoverBelowCallStackElement();
                });
            }

            let pair = this._summarySection.appendKeyValuePair(WI.UIString("Initiator"), fragment);
            pair.classList.add("initiator");

            if (this._popover && this._popover.visible)
                this._presentPopoverBelowCallStackElement();
        }
    }

    _refreshRedirectHeadersSections()
    {
        let referenceElement = this._redirectDetailsSections.length ? this._redirectDetailsSections.lastValue.element : this._summarySection.element;

        for (let i = this._redirectDetailsSections.length; i < this._resource.redirects.length; ++i) {
            let redirect = this._resource.redirects[i];

            let redirectRequestSection = new WI.ResourceDetailsSection(WI.UIString("Request"), "redirect");

            // FIXME: <https://webkit.org/b/190214> Web Inspector: expose full load metrics for redirect requests
            redirectRequestSection.appendKeyValuePair(`${redirect.requestMethod} ${redirect.urlComponents.path}`, null, "h1-status");

            for (let key in redirect.requestHeaders)
                redirectRequestSection.appendKeyValuePair(key, redirect.requestHeaders[key], "header");

            referenceElement = this.element.insertBefore(redirectRequestSection.element, referenceElement.nextElementSibling);
            this._redirectDetailsSections.push(redirectRequestSection);

            let redirectResponseSection = new WI.ResourceDetailsSection(WI.UIString("Redirect Response"), "redirect");

            // FIXME: <https://webkit.org/b/190214> Web Inspector: expose full load metrics for redirect requests
            redirectResponseSection.appendKeyValuePair(`${redirect.responseStatusCode} ${redirect.responseStatusText}`, null, "h1-status");

            for (let key in redirect.responseHeaders)
                redirectResponseSection.appendKeyValuePair(key, redirect.responseHeaders[key], "header");

            referenceElement = this.element.insertBefore(redirectResponseSection.element, referenceElement.nextElementSibling);
            this._redirectDetailsSections.push(redirectResponseSection);
        }
    }

    _refreshRequestHeadersSection()
    {
        let detailsElement = this._requestHeadersSection.detailsElement;
        detailsElement.removeChildren();

        // A revalidation request still sends a request even though we served from cache, so show the request.
        if (this._resource.statusCode !== 304) {
            if (this._resource.responseSource === WI.Resource.ResponseSource.MemoryCache) {
                this._requestHeadersSection.markIncompleteSectionWithMessage(WI.UIString("No request, served from the memory cache."));
                return;
            }
            if (this._resource.responseSource === WI.Resource.ResponseSource.DiskCache) {
                this._requestHeadersSection.markIncompleteSectionWithMessage(WI.UIString("No request, served from the disk cache."));
                return;
            }
        }

        let protocol = this._resource.protocol || "";
        let urlComponents = this._resource.urlComponents;
        if (protocol.startsWith("http/1")) {
            // HTTP/1.1 request line:
            // https://www.w3.org/Protocols/rfc2616/rfc2616-sec5.html#sec5.1
            let requestLine = `${this._resource.requestMethod} ${urlComponents.path} ${protocol.toUpperCase()}`;
            this._requestHeadersSection.appendKeyValuePair(requestLine, null, "h1-status");
        } else if (protocol === "h2") {
            // HTTP/2 Request pseudo headers:
            // https://tools.ietf.org/html/rfc7540#section-8.1.2.3
            this._requestHeadersSection.appendKeyValuePair(":method", this._resource.requestMethod, "h2-pseudo-header");
            this._requestHeadersSection.appendKeyValuePair(":scheme", urlComponents.scheme, "h2-pseudo-header");
            this._requestHeadersSection.appendKeyValuePair(":authority", WI.h2Authority(urlComponents), "h2-pseudo-header");
            this._requestHeadersSection.appendKeyValuePair(":path", WI.h2Path(urlComponents), "h2-pseudo-header");
        }

        let requestHeaders = this._resource.requestHeaders;
        for (let key in requestHeaders)
            this._requestHeadersSection.appendKeyValuePair(key, requestHeaders[key], "header");

        if (!detailsElement.firstChild)
            this._requestHeadersSection.markIncompleteSectionWithMessage(WI.UIString("No request headers"));
    }

    _refreshResponseHeadersSection()
    {
        let detailsElement = this._responseHeadersSection.detailsElement;
        detailsElement.removeChildren();

        if (!this._resource.hasResponse()) {
            this._responseHeadersSection.markIncompleteSectionWithLoadingIndicator();
            return;
        }

        this._responseHeadersSection.toggleIncomplete(false);

        let protocol = this._resource.protocol || "";
        if (protocol.startsWith("http/1")) {
            // HTTP/1.1 response status line:
            // https://www.w3.org/Protocols/rfc2616/rfc2616-sec6.html#sec6.1
            let responseLine = `${protocol.toUpperCase()} ${this._resource.statusCode} ${this._resource.statusText}`;
            this._responseHeadersSection.appendKeyValuePair(responseLine, null, "h1-status");
        } else if (protocol === "h2") {
            // HTTP/2 Response pseudo headers:
            // https://tools.ietf.org/html/rfc7540#section-8.1.2.4
            this._responseHeadersSection.appendKeyValuePair(":status", this._resource.statusCode, "h2-pseudo-header");
        }

        let responseHeaders = this._resource.responseHeaders;
        for (let key in responseHeaders) {
            // Split multiple Set-Cookie response headers out into their multiple headers instead of as a combined value.
            if (key.toLowerCase() === "set-cookie") {
                let responseCookies = this._resource.responseCookies;
                console.assert(responseCookies.length > 0);
                for (let cookie of responseCookies)
                    this._responseHeadersSection.appendKeyValuePair(key, cookie.header, "header");
                continue;
            }

            this._responseHeadersSection.appendKeyValuePair(key, responseHeaders[key], "header");
        }

        if (!detailsElement.firstChild)
            this._responseHeadersSection.markIncompleteSectionWithMessage(WI.UIString("No response headers"));
    }

    _refreshQueryStringSection()
    {
        if (!this._queryStringSection)
            return;

        let detailsElement = this._queryStringSection.detailsElement;
        detailsElement.removeChildren();

        let queryString = this._resource.urlComponents.queryString;
        let queryStringPairs = parseQueryString(queryString, true);
        for (let {name, value} of queryStringPairs)
            this._queryStringSection.appendKeyValuePair(name, value);
    }

    _refreshRequestDataSection()
    {
        if (!this._requestDataSection)
            return;

        let detailsElement = this._requestDataSection.detailsElement;
        detailsElement.removeChildren();

        let requestData = this._resource.requestData;
        let requestDataContentType = this._resource.requestDataContentType || "";

        if (requestDataContentType && requestDataContentType.match(/^application\/x-www-form-urlencoded\s*(;.*)?$/i)) {
            // Simple form data that should be parsable like a query string.
            this._requestDataSection.appendKeyValuePair(WI.UIString("MIME Type"), requestDataContentType);
            let queryStringPairs = parseQueryString(requestData, true);
            for (let {name, value} of queryStringPairs)
                this._requestDataSection.appendKeyValuePair(name, value);
            return;
        }

        let mimeTypeComponents = parseMIMEType(requestDataContentType);
        let mimeType = mimeTypeComponents.type;
        let boundary = mimeTypeComponents.boundary;
        let encoding = mimeTypeComponents.encoding;

        this._requestDataSection.appendKeyValuePair(WI.UIString("MIME Type"), mimeType);
        if (boundary)
            this._requestDataSection.appendKeyValuePair(WI.UIString("Boundary"), boundary);
        if (encoding)
            this._requestDataSection.appendKeyValuePair(WI.UIString("Encoding"), encoding);

        let goToButton = detailsElement.appendChild(WI.createGoToArrowButton());
        goToButton.addEventListener("click", () => { this._delegate.headersContentViewGoToRequestData(this); });
        this._requestDataSection.appendKeyValuePair(WI.UIString("Request Data"), goToButton);
    }

    _perfomSearchOnKeyValuePairs()
    {
        let searchRegex = WI.SearchUtilities.regExpForString(this._searchQuery, WI.SearchUtilities.defaultSettings);

        let elements = this.element.querySelectorAll(".key, .value");
        for (let element of elements) {
            let matchRanges = [];
            let text = element.textContent;
            let match;
            while (match = searchRegex.exec(text))
                matchRanges.push({offset: match.index, length: match[0].length});

            if (matchRanges.length) {
                let highlightedNodes = WI.highlightRangesWithStyleClass(element, matchRanges, "search-highlight", this._searchDOMChanges);
                this._searchResults = this._searchResults.concat(highlightedNodes);
            }
        }
    }

    _revealSearchResult(index, changeFocus)
    {
        let highlightElement = this._searchResults[index];
        if (!highlightElement)
            return;

        highlightElement.scrollIntoViewIfNeeded();

        if (!this._bouncyHighlightElement) {
            this._bouncyHighlightElement = document.createElement("div");
            this._bouncyHighlightElement.className = "bouncy-highlight";
            this._bouncyHighlightElement.addEventListener("animationend", (event) => {
                this._bouncyHighlightElement.remove();
            });
        }

        this._bouncyHighlightElement.remove();

        let computedStyles = window.getComputedStyle(highlightElement);
        let highlightElementRect = highlightElement.getBoundingClientRect();
        let contentViewRect = this.element.getBoundingClientRect();
        let contentViewScrollTop = this.element.scrollTop;
        let contentViewScrollLeft = this.element.scrollLeft;

        this._bouncyHighlightElement.textContent = highlightElement.textContent;
        this._bouncyHighlightElement.style.top = (highlightElementRect.top - contentViewRect.top + contentViewScrollTop) + "px";
        this._bouncyHighlightElement.style.left = (highlightElementRect.left - contentViewRect.left + contentViewScrollLeft) + "px";
        this._bouncyHighlightElement.style.fontWeight = computedStyles.fontWeight;

        this.element.appendChild(this._bouncyHighlightElement);
    }

    _presentPopoverBelowCallStackElement()
    {
        let bounds = WI.Rect.rectFromClientRect(this._popoverCallStackIconElement.getBoundingClientRect());
        this._popover.present(bounds.pad(2), [WI.RectEdge.MAX_Y, WI.RectEdge.MIN_Y, WI.RectEdge.MAX_X]);
    }

    _resourceMetricsDidChange(event)
    {
        this._needsSummaryRefresh = true;
        this._needsRequestHeadersRefresh = true;
        this._needsResponseHeadersRefresh = true;
        this.needsLayout();
    }

    _resourceRequestHeadersDidChange(event)
    {
        this._needsSummaryRefresh = true;
        this._needsRedirectHeadersRefresh = true;
        this._needsRequestHeadersRefresh = true;
        this.needsLayout();
    }

    _resourceResponseReceived(event)
    {
        this._needsSummaryRefresh = true;
        this._needsResponseHeadersRefresh = true;
        this.needsLayout();
    }
};
