/*
 * Copyright (C) 2013-2015 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.BreakpointTreeElement = class BreakpointTreeElement extends WI.GeneralTreeElement
{
    constructor(breakpoint, className, title)
    {
        console.assert(breakpoint instanceof WI.Breakpoint);

        if (!className)
            className = WI.BreakpointTreeElement.GenericLineIconStyleClassName;

        const subtitle = null;
        super(["breakpoint", className], title, subtitle, breakpoint);

        this._breakpoint = breakpoint;
        this._probeSet = null;

        this._listenerSet = new WI.EventListenerSet(this, "BreakpointTreeElement listeners");
        if (!title)
            this._listenerSet.register(breakpoint, WI.Breakpoint.Event.LocationDidChange, this._breakpointLocationDidChange);
        this._listenerSet.register(breakpoint, WI.Breakpoint.Event.DisabledStateDidChange, this._updateStatus);
        this._listenerSet.register(breakpoint, WI.Breakpoint.Event.AutoContinueDidChange, this._updateStatus);
        this._listenerSet.register(breakpoint, WI.Breakpoint.Event.ResolvedStateDidChange, this._updateStatus);
        this._listenerSet.register(WI.debuggerManager, WI.DebuggerManager.Event.BreakpointsEnabledDidChange, this._updateStatus);

        this._listenerSet.register(WI.probeManager, WI.ProbeManager.Event.ProbeSetAdded, this._probeSetAdded);
        this._listenerSet.register(WI.probeManager, WI.ProbeManager.Event.ProbeSetRemoved, this._probeSetRemoved);

        this._statusImageElement = document.createElement("img");
        this._statusImageElement.className = WI.BreakpointTreeElement.StatusImageElementStyleClassName;
        this._listenerSet.register(this._statusImageElement, "mousedown", this._statusImageElementMouseDown);
        this._listenerSet.register(this._statusImageElement, "click", this._statusImageElementClicked);

        if (!title)
            this._updateTitles();
        this._updateStatus();

        this.status = this._statusImageElement;

        this._iconAnimationLayerElement = document.createElement("span");
        this.iconElement.appendChild(this._iconAnimationLayerElement);
    }

    // Public

    get breakpoint()
    {
        return this._breakpoint;
    }

    get filterableData()
    {
        return {text: [this.breakpoint.contentIdentifier]};
    }

    ondelete()
    {
        if (!WI.debuggerManager.isBreakpointRemovable(this._breakpoint))
            return false;

        // We set this flag so that TreeOutlines that will remove this
        // BreakpointTreeElement will know whether it was deleted from
        // within the TreeOutline or from outside it (e.g. TextEditor).
        this.__deletedViaDeleteKeyboardShortcut = true;

        WI.debuggerManager.removeBreakpoint(this._breakpoint);
        return true;
    }

    onenter()
    {
        this._breakpoint.cycleToNextMode();
        return true;
    }

    onspace()
    {
        this._breakpoint.cycleToNextMode();
        return true;
    }

    onattach()
    {
        super.onattach();

        this._listenerSet.install();

        for (var probeSet of WI.probeManager.probeSets)
            if (probeSet.breakpoint === this._breakpoint)
                this._addProbeSet(probeSet);
    }

    ondetach()
    {
        super.ondetach();

        this._listenerSet.uninstall();

        if (this._probeSet)
            this._removeProbeSet(this._probeSet);
    }

    populateContextMenu(contextMenu, event)
    {
        WI.breakpointPopoverController.appendContextMenuItems(contextMenu, this._breakpoint, this._statusImageElement);

        super.populateContextMenu(contextMenu, event);
    }

    removeStatusImage()
    {
        this._statusImageElement.remove();
        this._statusImageElement = null;
    }

    // Private

    _updateTitles()
    {
        var sourceCodeLocation = this._breakpoint.sourceCodeLocation;

        var displayLineNumber = sourceCodeLocation.displayLineNumber;
        var displayColumnNumber = sourceCodeLocation.displayColumnNumber;
        if (displayColumnNumber > 0)
            this.mainTitle = WI.UIString("Line %d:%d").format(displayLineNumber + 1, displayColumnNumber + 1); // The user visible line and column numbers are 1-based.
        else
            this.mainTitle = WI.UIString("Line %d").format(displayLineNumber + 1); // The user visible line number is 1-based.

        if (sourceCodeLocation.hasMappedLocation()) {
            this.subtitle = sourceCodeLocation.formattedLocationString();

            if (sourceCodeLocation.hasFormattedLocation())
                this.subtitleElement.classList.add(WI.BreakpointTreeElement.FormattedLocationStyleClassName);
            else
                this.subtitleElement.classList.remove(WI.BreakpointTreeElement.FormattedLocationStyleClassName);

            this.tooltip = this.mainTitle + " \u2014 " + WI.UIString("originally %s").format(sourceCodeLocation.originalLocationString());
        }
    }

    _updateStatus()
    {
        if (!this._statusImageElement)
            return;

        if (this._breakpoint.disabled)
            this._statusImageElement.classList.add(WI.BreakpointTreeElement.StatusImageDisabledStyleClassName);
        else
            this._statusImageElement.classList.remove(WI.BreakpointTreeElement.StatusImageDisabledStyleClassName);

        if (this._breakpoint.autoContinue)
            this._statusImageElement.classList.add(WI.BreakpointTreeElement.StatusImageAutoContinueStyleClassName);
        else
            this._statusImageElement.classList.remove(WI.BreakpointTreeElement.StatusImageAutoContinueStyleClassName);

        if (this._breakpoint.resolved && WI.debuggerManager.breakpointsEnabled)
            this._statusImageElement.classList.add(WI.BreakpointTreeElement.StatusImageResolvedStyleClassName);
        else
            this._statusImageElement.classList.remove(WI.BreakpointTreeElement.StatusImageResolvedStyleClassName);
    }

    _addProbeSet(probeSet)
    {
        console.assert(probeSet instanceof WI.ProbeSet);
        console.assert(probeSet.breakpoint === this._breakpoint);
        console.assert(probeSet !== this._probeSet);

        this._probeSet = probeSet;
        probeSet.addEventListener(WI.ProbeSet.Event.SamplesCleared, this._samplesCleared, this);
        probeSet.dataTable.addEventListener(WI.ProbeSetDataTable.Event.FrameInserted, this._dataUpdated, this);
    }

    _removeProbeSet(probeSet)
    {
        console.assert(probeSet instanceof WI.ProbeSet);
        console.assert(probeSet === this._probeSet);

        probeSet.removeEventListener(WI.ProbeSet.Event.SamplesCleared, this._samplesCleared, this);
        probeSet.dataTable.removeEventListener(WI.ProbeSetDataTable.Event.FrameInserted, this._dataUpdated, this);
        this._probeSet = null;
    }

    _probeSetAdded(event)
    {
        var probeSet = event.data.probeSet;
        if (probeSet.breakpoint === this._breakpoint)
            this._addProbeSet(probeSet);
    }

    _probeSetRemoved(event)
    {
        var probeSet = event.data.probeSet;
        if (probeSet.breakpoint === this._breakpoint)
            this._removeProbeSet(probeSet);
    }

    _samplesCleared(event)
    {
        console.assert(this._probeSet);

        var oldTable = event.data.oldTable;
        oldTable.removeEventListener(WI.ProbeSetDataTable.Event.FrameInserted, this._dataUpdated, this);
        this._probeSet.dataTable.addEventListener(WI.ProbeSetDataTable.Event.FrameInserted, this._dataUpdated, this);
    }

    _dataUpdated()
    {
        if (this.element.classList.contains(WI.BreakpointTreeElement.ProbeDataUpdatedStyleClassName)) {
            clearTimeout(this._removeIconAnimationTimeoutIdentifier);
            this.element.classList.remove(WI.BreakpointTreeElement.ProbeDataUpdatedStyleClassName);
            // We want to restart the animation, which can only be done by removing the class,
            // performing layout, and re-adding the class. Try adding class back on next run loop.
            window.requestAnimationFrame(this._dataUpdated.bind(this));
            return;
        }

        this.element.classList.add(WI.BreakpointTreeElement.ProbeDataUpdatedStyleClassName);
        this._removeIconAnimationTimeoutIdentifier = setTimeout(() => {
            this.element.classList.remove(WI.BreakpointTreeElement.ProbeDataUpdatedStyleClassName);
        }, WI.BreakpointTreeElement.ProbeDataUpdatedAnimationDuration);
    }

    _breakpointLocationDidChange(event)
    {
        console.assert(event.target === this._breakpoint);

        // The Breakpoint has a new display SourceCode. The sidebar will remove us, and ondetach() will clear listeners.
        if (event.data.oldDisplaySourceCode === this._breakpoint.displaySourceCode)
            return;

        this._updateTitles();
    }

    _statusImageElementMouseDown(event)
    {
        // To prevent the tree element from selecting.
        event.stopPropagation();
    }

    _statusImageElementClicked(event)
    {
        this._breakpoint.cycleToNextMode();
    }
};

WI.BreakpointTreeElement.GenericLineIconStyleClassName = "breakpoint-generic-line-icon";
WI.BreakpointTreeElement.StatusImageElementStyleClassName = "status-image";
WI.BreakpointTreeElement.StatusImageResolvedStyleClassName = "resolved";
WI.BreakpointTreeElement.StatusImageAutoContinueStyleClassName = "auto-continue";
WI.BreakpointTreeElement.StatusImageDisabledStyleClassName = "disabled";
WI.BreakpointTreeElement.FormattedLocationStyleClassName = "formatted-location";
WI.BreakpointTreeElement.ProbeDataUpdatedStyleClassName = "data-updated";

WI.BreakpointTreeElement.ProbeDataUpdatedAnimationDuration = 400; // milliseconds
