/*
 * Copyright (C) 2015 Apple Inc. All rights reserved.
 * Copyright (C) 2013 University of Washington. 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.ProbeSetDetailsSection = class ProbeSetDetailsSection extends WI.DetailsSection
{
    constructor(probeSet)
    {
        console.assert(probeSet instanceof WI.ProbeSet, "Invalid ProbeSet argument:", probeSet);

        var optionsElement = document.createElement("div");
        var dataGrid = new WI.ProbeSetDataGrid(probeSet);

        var singletonRow = new WI.DetailsSectionRow;
        singletonRow.element.appendChild(dataGrid.element);

        var probeSectionGroup = new WI.DetailsSectionGroup([singletonRow]);

        super("probe", "", [probeSectionGroup], optionsElement);

        this.element.classList.add("probe-set");

        this._listenerSet = new WI.EventListenerSet(this, "ProbeSetDetailsSection UI listeners");
        this._probeSet = probeSet;
        this._dataGrid = dataGrid;

        this._navigationBar = new WI.NavigationBar;
        this._optionsElement.appendChild(this._navigationBar.element);

        this._addProbeButtonItem = new WI.ButtonNavigationItem("add-probe", WI.UIString("Add probe expression"), "Images/Plus13.svg", 13, 13);
        this._addProbeButtonItem.addEventListener(WI.ButtonNavigationItem.Event.Clicked, this._addProbeButtonClicked, this);
        this._navigationBar.addNavigationItem(this._addProbeButtonItem);

        this._clearSamplesButtonItem = new WI.ButtonNavigationItem("clear-samples", WI.UIString("Clear samples"), "Images/NavigationItemTrash.svg", 15, 15);
        this._clearSamplesButtonItem.addEventListener(WI.ButtonNavigationItem.Event.Clicked, this._clearSamplesButtonClicked, this);
        this._clearSamplesButtonItem.enabled = this._probeSetHasSamples();
        this._navigationBar.addNavigationItem(this._clearSamplesButtonItem);

        this._removeProbeButtonItem = new WI.ButtonNavigationItem("remove-probe", WI.UIString("Remove probe"), "Images/CloseLarge.svg", 12, 12);
        this._removeProbeButtonItem.addEventListener(WI.ButtonNavigationItem.Event.Clicked, this._removeProbeButtonClicked, this);
        this._navigationBar.addNavigationItem(this._removeProbeButtonItem);

        this._listenerSet.register(this._probeSet, WI.ProbeSet.Event.SampleAdded, this._probeSetSamplesChanged);
        this._listenerSet.register(this._probeSet, WI.ProbeSet.Event.SamplesCleared, this._probeSetSamplesChanged);

        // Update the source link when the breakpoint's resolved state changes,
        // so that it can become a live location link when possible.
        this._updateLinkElement();
        this._listenerSet.register(this._probeSet.breakpoint, WI.Breakpoint.Event.ResolvedStateDidChange, this._updateLinkElement);

        this._listenerSet.install();
    }

    // Public

    closed()
    {
        this._listenerSet.uninstall(true);
        this.element.remove();
    }

    // Protected

    sizeDidChange()
    {
        // FIXME: <https://webkit.org/b/152269> Web Inspector: Convert DetailsSection classes to use View
        this._dataGrid.sizeDidChange();
    }

    // Private

    _updateLinkElement()
    {
        const options = {
            ignoreNetworkTab: true,
            ignoreSearchTab: true,
        };

        var breakpoint = this._probeSet.breakpoint;
        if (breakpoint.sourceCodeLocation.sourceCode)
            this.titleElement = WI.createSourceCodeLocationLink(breakpoint.sourceCodeLocation, options);
        else {
            // Fallback for when we can't create a live source link.
            console.assert(!breakpoint.resolved);

            this.titleElement = WI.linkifyLocation(breakpoint.contentIdentifier, breakpoint.sourceCodeLocation.position, options);
        }

        this.titleElement.classList.add(WI.ProbeSetDetailsSection.DontFloatLinkStyleClassName);
    }

    _addProbeButtonClicked(event)
    {
        function createProbeFromEnteredExpression(visiblePopover, event)
        {
            if (event.keyCode !== 13)
                return;
            let expression = event.target.value;
            this._probeSet.createProbe(expression);
            visiblePopover.dismiss();
        }

        let popover = new WI.Popover;
        let content = document.createElement("div");
        content.classList.add(WI.ProbeSetDetailsSection.ProbePopoverElementStyleClassName);
        content.createChild("div").textContent = WI.UIString("Add New Probe Expression");
        let textBox = content.createChild("input");
        textBox.addEventListener("keypress", createProbeFromEnteredExpression.bind(this, popover));
        textBox.addEventListener("click", function (event) { event.target.select(); });
        textBox.type = "text";
        textBox.placeholder = WI.UIString("Expression");
        popover.content = content;
        let target = WI.Rect.rectFromClientRect(event.target.element.getBoundingClientRect());
        popover.present(target, [WI.RectEdge.MAX_Y, WI.RectEdge.MIN_Y, WI.RectEdge.MAX_X]);
        popover.windowResizeHandler = () => {
            let target = WI.Rect.rectFromClientRect(event.target.element.getBoundingClientRect());
            popover.present(target, [WI.RectEdge.MAX_Y, WI.RectEdge.MIN_Y, WI.RectEdge.MAX_X]);
        };
        textBox.select();
    }

    _clearSamplesButtonClicked(event)
    {
        this._probeSet.clearSamples();
    }

    _removeProbeButtonClicked(event)
    {
        this._probeSet.clear();
    }

    _probeSetSamplesChanged(event)
    {
        this._clearSamplesButtonItem.enabled = this._probeSetHasSamples();
    }

    _probeSetHasSamples()
    {
        return this._probeSet.probes.some((probe) => probe.samples.length);
    }
};

WI.ProbeSetDetailsSection.DontFloatLinkStyleClassName = "dont-float";
WI.ProbeSetDetailsSection.ProbePopoverElementStyleClassName = "probe-popover";
