/*
 * Copyright (C) 2018 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.ResourceSecurityContentView = class ResourceSecurityContentView extends WI.ContentView
{
    constructor(resource)
    {
        console.assert(resource instanceof WI.Resource);

        super();

        this._resource = resource;

        this._insecureMessageElement = null;
        this._needsConnectionRefresh = true;
        this._needsCertificateRefresh = true;

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

        this.element.classList.add("resource-details", "resource-security");
    }

    // Protected

    initialLayout()
    {
        super.initialLayout();

        this._connectionSection = new WI.ResourceDetailsSection(WI.UIString("Connection"), "connection");
        this.element.appendChild(this._connectionSection.element);

        this._certificateSection = new WI.ResourceDetailsSection(WI.UIString("Certificate"), "certificate");
        this.element.appendChild(this._certificateSection.element);

        this._resource.addEventListener(WI.Resource.Event.ResponseReceived, this._handleResourceResponseReceived, this);
        this._resource.addEventListener(WI.Resource.Event.MetricsDidChange, this._handleResourceMetricsDidChange, this);
    }

    layout()
    {
        super.layout();

        if (!this._resource.loadedSecurely) {
            if (!this._insecureMessageElement)
                this._insecureMessageElement = WI.createMessageTextView(WI.UIString("The resource was requested insecurely."), true);
            this.element.appendChild(this._insecureMessageElement);
            return;
        }

        if (this._needsConnectionRefresh) {
            this._needsConnectionRefresh = false;
            this._refreshConnectionSection();
        }

        if (this._needsCertificateRefresh) {
            this._needsCertificateRefresh = false;
            this._refreshCetificateSection();
        }
    }

    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 < this._searchResults.length - 1)
            ++this._searchIndex;
        else
            this._searchIndex = 0;

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

    // Private

    _refreshConnectionSection()
    {
        let detailsElement = this._connectionSection.detailsElement;
        detailsElement.removeChildren();

        let security = this._resource.security;
        if (isEmptyObject(security)) {
            this._connectionSection.markIncompleteSectionWithMessage(WI.UIString("No connection security information."));
            return;
        }

        let connection = security.connection;
        if (isEmptyObject(connection) || Object.values(connection).every((value) => !value)) {
            this._connectionSection.markIncompleteSectionWithMessage(WI.UIString("No connection security information."));
            return;
        }

        this._connectionSection.appendKeyValuePair(WI.UIString("Protocol"), connection.protocol || emDash);
        this._connectionSection.appendKeyValuePair(WI.UIString("Cipher"), connection.cipher || emDash);
    }

    _refreshCetificateSection()
    {
        let detailsElement = this._certificateSection.detailsElement;
        detailsElement.removeChildren();

        let security = this._resource.security;
        if (isEmptyObject(security)) {
            this._certificateSection.markIncompleteSectionWithMessage(WI.UIString("No certificate security information."));
            return;
        }

        let certificate = security.certificate;
        if (isEmptyObject(certificate) || Object.values(certificate).every((value) => !value)) {
            this._certificateSection.markIncompleteSectionWithMessage(WI.UIString("No certificate security information."));
            return;
        }

        if (WI.NetworkManager.supportsShowCertificate()) {
            let button = document.createElement("button");
            button.textContent = WI.UIString("Show full certificate");

            let errorElement = null;
            button.addEventListener("click", (event) => {
                this._resource.showCertificate()
                .then(() => {
                    if (errorElement) {
                        errorElement.remove();
                        errorElement = null;
                    }
                })
                .catch((error) => {
                    if (!errorElement)
                        errorElement = WI.ImageUtilities.useSVGSymbol("Images/Error.svg", "error", error);
                    button.insertAdjacentElement("afterend", errorElement);
                });
            });

            let pairElement = this._certificateSection.appendKeyValuePair(button);
            pairElement.classList.add("show-certificate");
        }

        this._certificateSection.appendKeyValuePair(WI.UIString("Subject"), certificate.subject || emDash);

        let appendFormattedDate = (key, timestamp) => {
            if (isNaN(timestamp))
                return;

            let date = new Date(timestamp * 1000);

            let timeElement = document.createElement("time");
            timeElement.datetime = date.toISOString();
            timeElement.textContent = date.toLocaleString();
            this._certificateSection.appendKeyValuePair(key, timeElement);

        };
        appendFormattedDate(WI.UIString("Valid From"), certificate.validFrom);
        appendFormattedDate(WI.UIString("Valid Until"), certificate.validUntil);

        let appendList = (key, values, className) => {
            if (!Array.isArray(values))
                return;

            const initialCount = 5;
            for (let i = 0; i < Math.min(values.length, initialCount); ++i)
                this._certificateSection.appendKeyValuePair(key, values[i], className);

            let remaining = values.length - initialCount;
            if (remaining <= 0)
                return;

            let showMoreElement = document.createElement("a");
            showMoreElement.classList.add("show-more");
            showMoreElement.textContent = WI.UIString("Show %d More").format(remaining);

            let showMorePair = this._certificateSection.appendKeyValuePair(key, showMoreElement, className);

            showMoreElement.addEventListener("click", (event) => {
                showMorePair.remove();

                for (let i = initialCount; i < values.length; ++i)
                    this._certificateSection.appendKeyValuePair(key, values[i], className);
            }, {once: true});
        };
        appendList(WI.UIString("DNS"), certificate.dnsNames, "dns-name");
        appendList(WI.UIString("IP"), certificate.ipAddresses, "ip-address");
    }

    _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);
    }

    _handleResourceResponseReceived(event)
    {
        this._needsCertificateRefresh = true;
        this.needsLayout();
    }

    _handleResourceMetricsDidChange(event)
    {
        this._needsConnectionRefresh = true;
        this.needsLayout();
    }
};
