/*
 * 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.WebSocketContentView = class WebSocketContentView extends WI.ContentView
{
    constructor(resource)
    {
        console.assert(resource instanceof WI.WebSocketResource, resource);

        super(resource);

        this._updateFramesDebouncer = new Debouncer(() => {
            this._updateFrames();
        });

        this._resource = resource;
        this._framesRendered = 0;
        this._lastRenderedReadyState = null;

        // COMPATIBILITY (iOS 10.3): `walltime` did not exist in 10.3 and earlier.
        this._showTimeColumn = InspectorBackend.domains.Network.hasEventParameter("webSocketWillSendHandshakeRequest", "walltime");

        this.element.classList.add("web-socket", "resource");

        let columns = {data: {}};
        columns.data.title = WI.UIString("Data");
        columns.data.sortable = false;
        columns.data.width = "85%";

        if (this._showTimeColumn)
            columns.time = {title: WI.UIString("Time"), sortable: true};

        this._dataGrid = new WI.DataGrid(columns);
        this._dataGrid.variableHeightRows = true;
        this.addSubview(this._dataGrid);

        this._addRow(WI.UIString("WebSocket Connection Established"), this._resource.walltime);

        this._dataGrid.updateLayout();
    }

    // Static

    static textForOpcode(opcode)
    {
        switch (opcode) {
        case WI.WebSocketResource.OpCodes.ContinuationFrame:
            return WI.UIString("Continuation Frame");
        case WI.WebSocketResource.OpCodes.TextFrame:
            return WI.UIString("Text Frame");
        case WI.WebSocketResource.OpCodes.BinaryFrame:
            return WI.UIString("Binary Frame");
        case WI.WebSocketResource.OpCodes.ConnectionCloseFrame:
            return WI.UIString("Connection Close Frame");
        case WI.WebSocketResource.OpCodes.PingFrame:
            return WI.UIString("Ping Frame");
        case WI.WebSocketResource.OpCodes.PongFrame:
            return WI.UIString("Pong Frame");
        }
    }

    // Public

    shown()
    {
        this._updateFramesDebouncer.force();
        this._resource.addEventListener(WI.WebSocketResource.Event.FrameAdded, this._updateFramesSoon, this);
        this._resource.addEventListener(WI.WebSocketResource.Event.ReadyStateChanged, this._updateFramesSoon, this);
    }

    hidden()
    {
        this._resource.removeEventListener(WI.WebSocketResource.Event.FrameAdded, this._updateFramesSoon, this);
        this._resource.removeEventListener(WI.WebSocketResource.Event.ReadyStateChanged, this._updateFramesSoon, this);
    }

    // Private

    _updateFramesSoon()
    {
        this._updateFramesDebouncer.delayForFrame();
    }

    _updateFrames()
    {
        let shouldScrollToBottom = this._dataGrid.isScrolledToLastRow();

        let framesLength = this._resource.frames.length;
        for (let index = this._framesRendered; index < framesLength; index++) {
            let frame = this._resource.frames[index];
            let {data, isOutgoing, opcode, walltime} = frame;
            this._addFrame(data, isOutgoing, opcode, walltime);
        }

        this._framesRendered = framesLength;

        if (this._lastRenderedReadyState !== this._resource.readyState) {
            if (this._resource.readyState === WI.WebSocketResource.ReadyState.Closed)
                this._dataGrid.appendChild(new WI.SpanningDataGridNode(WI.UIString("Connection Closed")));

            this._lastRenderedReadyState = this._resource.readyState;
        }

        if (shouldScrollToBottom) {
            if (!this._scrollToLastRowDebouncer) {
                this._scrollToLastRowDebouncer = new Debouncer(() => {
                    this._dataGrid.scrollToLastRow();
                });
            }

            this._scrollToLastRowDebouncer.delayForFrame();
        }
    }

    _addFrame(data, isOutgoing, opcode, time)
    {
        let nodeText;
        let isText = opcode === WI.WebSocketResource.OpCodes.TextFrame;
        if (isText)
            nodeText = data;
        else
            nodeText = WI.WebSocketContentView.textForOpcode(opcode);

        this._addRow(nodeText, time, {isOutgoing, isText});
    }

    _addRow(data, time, attributes = {})
    {
        let node;
        if (this._showTimeColumn)
            node = new WI.WebSocketDataGridNode({...attributes, data, time});
        else
            node = new WI.WebSocketDataGridNode({...attributes, data});

        this._dataGrid.appendChild(node);

        if (attributes.isText)
            node.element.classList.add("text-frame");
        else
            node.element.classList.add("non-text-frame");

        if (attributes.isOutgoing)
            node.element.classList.add("outgoing");
        else
            node.element.classList.add("incoming");
    }
};
