/*
 * 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.ResourceSizesContentView = class ResourceSizesContentView 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.SizeDidChange, this._resourceSizeDidChange, this);
        this._resource.addEventListener(WI.Resource.Event.TransferSizeDidChange, this._resourceTransferSizeDidChange, this);
        this._resource.addEventListener(WI.Resource.Event.MetricsDidChange, this._resourceMetricsDidChange, this);

        this._delegate = delegate;

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

        this._needsTransferSizesRefresh = false;
        this._needsResourceSizeRefresh = false;
    }

    // Protected

    initialLayout()
    {
        super.initialLayout();

        let contentElement = this.element.appendChild(document.createElement("div"));
        contentElement.className = "content";

        let networkSection = contentElement.appendChild(document.createElement("section"));
        networkSection.className = "network split";

        function createSizeComponents(parentElement, subtitle, imageSource, label1, label2) {
            let subtitleElement = parentElement.appendChild(document.createElement("div"));
            subtitleElement.className = "subtitle";
            subtitleElement.textContent = subtitle;

            let container = parentElement.appendChild(document.createElement("div"));
            container.className = "container";

            let imageElement = container.appendChild(document.createElement("img"));
            if (imageSource)
                imageElement.src = imageSource;

            let groupElement = container.appendChild(document.createElement("div"));
            groupElement.className = "bytes-group";

            let bytesElement = groupElement.appendChild(document.createElement("div"));
            bytesElement.className = "bytes";

            let suffixElement = groupElement.appendChild(document.createElement("div"));
            suffixElement.className = "suffix";

            let table = parentElement.appendChild(document.createElement("table"));
            let headerRow = table.appendChild(document.createElement("tr"));
            let label1Element = headerRow.appendChild(document.createElement("td"));
            let value1Element = headerRow.appendChild(document.createElement("td"));
            let bodyRow = table.appendChild(document.createElement("tr"));
            let label2Element = bodyRow.appendChild(document.createElement("td"));
            let value2Element = bodyRow.appendChild(document.createElement("td"));

            label1Element.textContent = label1;
            label1Element.className = "label";
            label2Element.textContent = label2;
            label2Element.className = "label";

            return {
                container,
                bytesElement,
                suffixElement,
                imageElement,
                value1Element,
                value2Element,
            };
        }

        let sendingSection = networkSection.appendChild(document.createElement("div"));
        sendingSection.className = "subsection";

        let sendingComponents = createSizeComponents(sendingSection, WI.UIString("Bytes Sent"), "Images/Sending.svg", WI.UIString("Headers:"), WI.UIString("Body:"));
        this._sendingBytesElement = sendingComponents.bytesElement;
        this._sendingBytesSuffixElement = sendingComponents.suffixElement;
        this._sendingHeaderBytesElement = sendingComponents.value1Element;
        this._sendingBodyBytesElement = sendingComponents.value2Element;

        let bytesDivider = networkSection.appendChild(document.createElement("div"));
        bytesDivider.className = "divider";

        let receivingSection = networkSection.appendChild(document.createElement("div"));
        receivingSection.className = "subsection";

        let receivingComponents = createSizeComponents(receivingSection, WI.UIString("Bytes Received"), "Images/Receiving.svg", WI.UIString("Headers:"), WI.UIString("Body:"));
        this._receivingBytesElement = receivingComponents.bytesElement;
        this._receivingBytesSuffixElement = receivingComponents.suffixElement;
        this._receivingHeaderBytesElement = receivingComponents.value1Element;
        this._receivingBodyBytesElement = receivingComponents.value2Element;

        let resourceDivider = networkSection.appendChild(document.createElement("div"));
        resourceDivider.className = "divider";

        let resourceSection = networkSection.appendChild(document.createElement("div"));
        resourceSection.className = "subsection large";

        let resourceComponents = createSizeComponents(resourceSection, WI.UIString("Resource Size"), null, WI.UIString("Compression:"), WI.UIString("MIME Type:"));
        resourceComponents.container.classList.add(WI.ResourceTreeElement.ResourceIconStyleClassName, ...WI.Resource.classNamesForResource(this._resource));
        resourceComponents.imageElement.classList.add("icon");
        this._resourceBytesElement = resourceComponents.bytesElement;
        this._resourceBytesSuffixElement = resourceComponents.suffixElement;
        this._compressionElement = resourceComponents.value1Element;
        this._contentTypeElement = resourceComponents.value2Element;

        this._refreshTransferSizeSections();
        this._refreshResourceSizeSection();

        this._needsTransferSizesRefresh = false;
        this._needsResourceSizeRefresh = false;
    }

    layout()
    {
        super.layout();

        if (this._needsTransferSizesRefresh) {
            this._refreshTransferSizeSections();
            this._needsTransferSizesRefresh = false;
        }

        if (this._needsResourceSizeRefresh) {
            this._refreshResourceSizeSection();
            this._needsResourceSizeRefresh = false;
        }
    }

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

        super.closed();
    }

    // Private

    _sizeComponents(bytes)
    {
        console.assert(bytes >= 0);

        // Prefer KB over B. And prefer 1 decimal point to keep sizes simple
        // but we will still need B if bytes is less than 0.1 KB.
        if (bytes < 103)
            return [bytes.toFixed(0), "B"];

        let kilobytes = bytes / 1024;
        if (kilobytes < 1024)
            return [kilobytes.toFixed(1), "KB"];

        let megabytes = kilobytes / 1024;
        if (megabytes < 1024)
            return [megabytes.toFixed(1), "MB"];

        let gigabytes = megabytes / 1024;
        return [gigabytes.toFixed(1), "GB"];
    }

    _refreshTransferSizeSections()
    {
        let bytesSentHeader = this._resource.requestHeadersTransferSize;
        let bytesSentBody = this._resource.requestBodyTransferSize;
        let bytesSent = bytesSentHeader + bytesSentBody;

        let bytesReceivedHeader = this._resource.responseHeadersTransferSize;
        let bytesReceivedBody = this._resource.responseBodyTransferSize;
        let bytesReceived = bytesReceivedHeader + bytesReceivedBody;

        let [sentValue, sentSuffix] = this._sizeComponents(bytesSent || 0);
        this._sendingBytesElement.textContent = sentValue;
        this._sendingBytesSuffixElement.textContent = sentSuffix;

        this._sendingHeaderBytesElement.textContent = bytesSentHeader ? Number.bytesToString(bytesSentHeader) : emDash;
        this._sendingBodyBytesElement.textContent = bytesSentBody ? Number.bytesToString(bytesSentBody) : emDash;

        let [receivedValue, receivedSuffix] = this._sizeComponents(bytesReceived || 0);
        this._receivingBytesElement.textContent = receivedValue;
        this._receivingBytesSuffixElement.textContent = receivedSuffix;

        this._receivingHeaderBytesElement.textContent = bytesReceivedHeader ? Number.bytesToString(bytesReceivedHeader) : emDash;
        this._receivingBodyBytesElement.textContent = bytesReceivedBody ? Number.bytesToString(bytesReceivedBody) : emDash;

        function appendGoToArrow(parentElement, handler) {
            let goToButton = parentElement.appendChild(WI.createGoToArrowButton());
            goToButton.addEventListener("click", handler);
        }

        if (bytesSentHeader)
            appendGoToArrow(this._sendingHeaderBytesElement, () => { this._delegate.sizesContentViewGoToHeaders(this); });
        if (bytesSentBody)
            appendGoToArrow(this._sendingBodyBytesElement, () => { this._delegate.sizesContentViewGoToRequestBody(this); });
        if (bytesReceivedHeader)
            appendGoToArrow(this._receivingHeaderBytesElement, () => { this._delegate.sizesContentViewGoToHeaders(this); });
        if (bytesReceivedBody)
            appendGoToArrow(this._receivingBodyBytesElement, () => { this._delegate.sizesContentViewGoToResponseBody(this); });
    }

    _refreshResourceSizeSection()
    {
        let encodedSize = !isNaN(this._resource.networkEncodedSize) ? this._resource.networkEncodedSize : this._resource.estimatedNetworkEncodedSize;
        let decodedSize = !isNaN(this._resource.networkDecodedSize) ? this._resource.networkDecodedSize : this._resource.size;
        let compressionRate = decodedSize / encodedSize;
        let compressionString = compressionRate > 0 && isFinite(compressionRate) ? WI.UIString("%.2f\u00d7").format(compressionRate) : WI.UIString("None");

        let [resourceSizeValue, resourceSizeSuffix] = this._sizeComponents(decodedSize || 0);
        this._resourceBytesElement.textContent = resourceSizeValue;
        this._resourceBytesSuffixElement.textContent = resourceSizeSuffix;

        let contentEncoding = this._resource.responseHeaders.valueForCaseInsensitiveKey("Content-Encoding");
        if (contentEncoding)
            compressionString += ` (${contentEncoding.toLowerCase()})`;

        this._compressionElement.textContent = compressionString;
        this._contentTypeElement.textContent = this._resource.mimeType || emDash;

        const minimumSizeBeforeWarning = 1024;
        if (compressionRate <= 1 && encodedSize >= minimumSizeBeforeWarning && WI.shouldTreatMIMETypeAsText(this._resource.mimeType))
            this._compressionElement.appendChild(WI.ImageUtilities.useSVGSymbol("Images/Warning.svg", "warning", WI.UIString("This text resource could benefit from compression")));
    }

    _resourceSizeDidChange(event)
    {
        this._needsTransferSizesRefresh = true;
        this.needsLayout();
    }

    _resourceTransferSizeDidChange(event)
    {
        this._needsTransferSizesRefresh = true;
        this.needsLayout();
    }

    _resourceMetricsDidChange(event)
    {
        this._needsTransferSizesRefresh = true;
        this._needsResourceSizeRefresh = true;
        this.needsLayout();
    }
};
