/*
 * Copyright (C) 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.BreakpointPopoverController = class BreakpointPopoverController extends WI.Object
{
    constructor()
    {
        super();

        this._breakpoint = null;
        this._popover = null;
        this._popoverContentElement = null;
    }

    // Public

    appendContextMenuItems(contextMenu, breakpoint, breakpointDisplayElement)
    {
        console.assert(document.body.contains(breakpointDisplayElement), "Breakpoint popover display element must be in the DOM.");

        const editBreakpoint = () => {
            console.assert(!this._popover, "Breakpoint popover already exists.");
            if (this._popover)
                return;

            this._createPopoverContent(breakpoint);
            this._popover = new WI.Popover(this);
            this._popover.content = this._popoverContentElement;

            let bounds = WI.Rect.rectFromClientRect(breakpointDisplayElement.getBoundingClientRect());
            bounds.origin.x -= 1; // Move the anchor left one pixel so it looks more centered.
            this._popover.present(bounds.pad(2), [WI.RectEdge.MAX_Y]);
        };

        const removeBreakpoint = () => {
            WI.debuggerManager.removeBreakpoint(breakpoint);
        };

        const toggleBreakpoint = () => {
            breakpoint.disabled = !breakpoint.disabled;
        };

        const toggleAutoContinue = () => {
            breakpoint.autoContinue = !breakpoint.autoContinue;
        };

        const revealOriginalSourceCodeLocation = () => {
            const options = {
                ignoreNetworkTab: true,
                ignoreSearchTab: true,
            };
            WI.showOriginalOrFormattedSourceCodeLocation(breakpoint.sourceCodeLocation, options);
        };

        if (WI.debuggerManager.isBreakpointEditable(breakpoint))
            contextMenu.appendItem(WI.UIString("Edit Breakpoint\u2026"), editBreakpoint);

        if (breakpoint.autoContinue && !breakpoint.disabled) {
            contextMenu.appendItem(WI.UIString("Disable Breakpoint"), toggleBreakpoint);
            contextMenu.appendItem(WI.UIString("Cancel Automatic Continue"), toggleAutoContinue);
        } else if (!breakpoint.disabled)
            contextMenu.appendItem(WI.UIString("Disable Breakpoint"), toggleBreakpoint);
        else
            contextMenu.appendItem(WI.UIString("Enable Breakpoint"), toggleBreakpoint);

        if (!breakpoint.autoContinue && !breakpoint.disabled && breakpoint.actions.length)
            contextMenu.appendItem(WI.UIString("Set to Automatically Continue"), toggleAutoContinue);

        if (WI.debuggerManager.isBreakpointRemovable(breakpoint))
            contextMenu.appendItem(WI.UIString("Delete Breakpoint"), removeBreakpoint);

        if (breakpoint._sourceCodeLocation.hasMappedLocation()) {
            contextMenu.appendSeparator();
            contextMenu.appendItem(WI.UIString("Reveal in Original Resource"), revealOriginalSourceCodeLocation);
        }
    }

    // CodeMirrorCompletionController delegate

    completionControllerShouldAllowEscapeCompletion()
    {
        return false;
    }

    // Private

    _createPopoverContent(breakpoint)
    {
        console.assert(!this._popoverContentElement, "Popover content element already exists.");
        if (this._popoverContentElement)
            return;

        this._breakpoint = breakpoint;
        this._popoverContentElement = document.createElement("div");
        this._popoverContentElement.className = "edit-breakpoint-popover-content";

        let checkboxElement = document.createElement("input");
        checkboxElement.type = "checkbox";
        checkboxElement.checked = !this._breakpoint.disabled;
        checkboxElement.addEventListener("change", this._popoverToggleEnabledCheckboxChanged.bind(this));

        let checkboxLabel = document.createElement("label");
        checkboxLabel.className = "toggle";
        checkboxLabel.appendChild(checkboxElement);
        checkboxLabel.append(this._breakpoint.sourceCodeLocation.displayLocationString());

        let table = document.createElement("table");

        let conditionRow = table.appendChild(document.createElement("tr"));
        let conditionHeader = conditionRow.appendChild(document.createElement("th"));
        let conditionData = conditionRow.appendChild(document.createElement("td"));
        let conditionLabel = conditionHeader.appendChild(document.createElement("label"));
        conditionLabel.textContent = WI.UIString("Condition");
        let conditionEditorElement = conditionData.appendChild(document.createElement("div"));
        conditionEditorElement.classList.add("edit-breakpoint-popover-condition", WI.SyntaxHighlightedStyleClassName);

        this._conditionCodeMirror = WI.CodeMirrorEditor.create(conditionEditorElement, {
            extraKeys: {Tab: false},
            lineWrapping: false,
            mode: "text/javascript",
            matchBrackets: true,
            placeholder: WI.UIString("Conditional expression"),
            scrollbarStyle: null,
            value: this._breakpoint.condition || "",
        });

        let conditionCodeMirrorInputField = this._conditionCodeMirror.getInputField();
        conditionCodeMirrorInputField.id = "codemirror-condition-input-field";
        conditionLabel.setAttribute("for", conditionCodeMirrorInputField.id);

        this._conditionCodeMirrorEscapeOrEnterKeyHandler = this._conditionCodeMirrorEscapeOrEnterKey.bind(this);
        this._conditionCodeMirror.addKeyMap({
            "Esc": this._conditionCodeMirrorEscapeOrEnterKeyHandler,
            "Enter": this._conditionCodeMirrorEscapeOrEnterKeyHandler,
        });

        this._conditionCodeMirror.on("change", this._conditionCodeMirrorChanged.bind(this));
        this._conditionCodeMirror.on("beforeChange", this._conditionCodeMirrorBeforeChange.bind(this));

        let completionController = new WI.CodeMirrorCompletionController(this._conditionCodeMirror, this);
        completionController.addExtendedCompletionProvider("javascript", WI.javaScriptRuntimeCompletionProvider);

        // CodeMirror needs a refresh after the popover displays, to layout, otherwise it doesn't appear.
        setTimeout(() => {
            this._conditionCodeMirror.refresh();
            this._conditionCodeMirror.focus();
        }, 0);

        // COMPATIBILITY (iOS 9): Legacy backends don't support breakpoint ignore count.
        // Since support can't be tested directly, check for Runtime.run (iOS 9.3) or Console.heapSnapshot (iOS 10.0+).
        // FIXME: Use explicit version checking once https://webkit.org/b/148680 is fixed.
        if (InspectorBackend.hasCommand("Console.heapSnapshot") || InspectorBackend.hasCommand("Runtime.run")) {
            let ignoreCountRow = table.appendChild(document.createElement("tr"));
            let ignoreCountHeader = ignoreCountRow.appendChild(document.createElement("th"));
            let ignoreCountLabel = ignoreCountHeader.appendChild(document.createElement("label"));
            let ignoreCountData = ignoreCountRow.appendChild(document.createElement("td"));
            this._ignoreCountInput = ignoreCountData.appendChild(document.createElement("input"));
            this._ignoreCountInput.id = "edit-breakpoint-popover-ignore";
            this._ignoreCountInput.type = "number";
            this._ignoreCountInput.min = 0;
            this._ignoreCountInput.value = 0;
            this._ignoreCountInput.addEventListener("change", this._popoverIgnoreInputChanged.bind(this));

            ignoreCountLabel.setAttribute("for", this._ignoreCountInput.id);
            ignoreCountLabel.textContent = WI.UIString("Ignore");

            this._ignoreCountText = ignoreCountData.appendChild(document.createElement("span"));
            this._updateIgnoreCountText();
        }

        let actionRow = table.appendChild(document.createElement("tr"));
        let actionHeader = actionRow.appendChild(document.createElement("th"));
        let actionData = this._actionsContainer = actionRow.appendChild(document.createElement("td"));
        let actionLabel = actionHeader.appendChild(document.createElement("label"));
        actionLabel.textContent = WI.UIString("Action");

        if (!this._breakpoint.actions.length)
            this._popoverActionsCreateAddActionButton();
        else {
            this._popoverContentElement.classList.add(WI.BreakpointPopoverController.WidePopoverClassName);
            for (let i = 0; i < this._breakpoint.actions.length; ++i) {
                let breakpointActionView = new WI.BreakpointActionView(this._breakpoint.actions[i], this, true);
                this._popoverActionsInsertBreakpointActionView(breakpointActionView, i);
            }
        }

        let optionsRow = this._popoverOptionsRowElement = table.appendChild(document.createElement("tr"));
        if (!this._breakpoint.actions.length)
            optionsRow.classList.add(WI.BreakpointPopoverController.HiddenStyleClassName);
        let optionsHeader = optionsRow.appendChild(document.createElement("th"));
        let optionsData = optionsRow.appendChild(document.createElement("td"));
        let optionsLabel = optionsHeader.appendChild(document.createElement("label"));
        let optionsCheckbox = this._popoverOptionsCheckboxElement = optionsData.appendChild(document.createElement("input"));
        let optionsCheckboxLabel = optionsData.appendChild(document.createElement("label"));
        optionsCheckbox.id = "edit-breakpoint-popover-auto-continue";
        optionsCheckbox.type = "checkbox";
        optionsCheckbox.checked = this._breakpoint.autoContinue;
        optionsCheckbox.addEventListener("change", this._popoverToggleAutoContinueCheckboxChanged.bind(this));
        optionsLabel.textContent = WI.UIString("Options");
        optionsCheckboxLabel.setAttribute("for", optionsCheckbox.id);
        optionsCheckboxLabel.textContent = WI.UIString("Automatically continue after evaluating");

        this._popoverContentElement.appendChild(checkboxLabel);
        this._popoverContentElement.appendChild(table);
    }

    _popoverToggleEnabledCheckboxChanged(event)
    {
        this._breakpoint.disabled = !event.target.checked;
    }

    _conditionCodeMirrorChanged(codeMirror, change)
    {
        this._breakpoint.condition = (codeMirror.getValue() || "").trim();
    }

    _conditionCodeMirrorBeforeChange(codeMirror, change)
    {
        if (change.update) {
            let newText = change.text.join("").replace(/\n/g, "");
            change.update(change.from, change.to, [newText]);
        }

        return true;
    }

    _conditionCodeMirrorEscapeOrEnterKey()
    {
        if (!this._popover)
            return;

        this._popover.dismiss();
    }

    _popoverIgnoreInputChanged(event)
    {
        let ignoreCount = 0;
        if (event.target.value) {
            ignoreCount = parseInt(event.target.value, 10);
            if (isNaN(ignoreCount) || ignoreCount < 0)
                ignoreCount = 0;
        }

        this._ignoreCountInput.value = ignoreCount;
        this._breakpoint.ignoreCount = ignoreCount;

        this._updateIgnoreCountText();
    }

    _popoverToggleAutoContinueCheckboxChanged(event)
    {
        this._breakpoint.autoContinue = event.target.checked;
    }

    _popoverActionsCreateAddActionButton()
    {
        this._popoverContentElement.classList.remove(WI.BreakpointPopoverController.WidePopoverClassName);
        this._actionsContainer.removeChildren();

        let addActionButton = this._actionsContainer.appendChild(document.createElement("button"));
        addActionButton.textContent = WI.UIString("Add Action");
        addActionButton.addEventListener("click", this._popoverActionsAddActionButtonClicked.bind(this));
    }

    _popoverActionsAddActionButtonClicked(event)
    {
        this._popoverContentElement.classList.add(WI.BreakpointPopoverController.WidePopoverClassName);
        this._actionsContainer.removeChildren();

        let newAction = this._breakpoint.createAction(WI.BreakpointAction.Type.Log);
        let newBreakpointActionView = new WI.BreakpointActionView(newAction, this);
        this._popoverActionsInsertBreakpointActionView(newBreakpointActionView, -1);
        this._popoverOptionsRowElement.classList.remove(WI.BreakpointPopoverController.HiddenStyleClassName);
        this._popover.update();
    }

    _popoverActionsInsertBreakpointActionView(breakpointActionView, index)
    {
        if (index === -1)
            this._actionsContainer.appendChild(breakpointActionView.element);
        else {
            let nextElement = this._actionsContainer.children[index + 1] || null;
            this._actionsContainer.insertBefore(breakpointActionView.element, nextElement);
        }
    }

    _updateIgnoreCountText()
    {
        if (this._breakpoint.ignoreCount === 1)
            this._ignoreCountText.textContent = WI.UIString("time before stopping");
        else
            this._ignoreCountText.textContent = WI.UIString("times before stopping");
    }

    breakpointActionViewAppendActionView(breakpointActionView, newAction)
    {
        let newBreakpointActionView = new WI.BreakpointActionView(newAction, this);

        let index = 0;
        let children = this._actionsContainer.children;
        for (let i = 0; children.length; ++i) {
            if (children[i] === breakpointActionView.element) {
                index = i;
                break;
            }
        }

        this._popoverActionsInsertBreakpointActionView(newBreakpointActionView, index);
        this._popoverOptionsRowElement.classList.remove(WI.BreakpointPopoverController.HiddenStyleClassName);

        this._popover.update();
    }

    breakpointActionViewRemoveActionView(breakpointActionView)
    {
        breakpointActionView.element.remove();

        if (!this._actionsContainer.children.length) {
            this._popoverActionsCreateAddActionButton();
            this._popoverOptionsRowElement.classList.add(WI.BreakpointPopoverController.HiddenStyleClassName);
            this._popoverOptionsCheckboxElement.checked = false;
        }

        this._popover.update();
    }

    breakpointActionViewResized(breakpointActionView)
    {
        this._popover.update();
    }

    willDismissPopover(popover)
    {
        console.assert(this._popover === popover);
        this._popoverContentElement = null;
        this._popoverOptionsRowElement = null;
        this._popoverOptionsCheckboxElement = null;
        this._actionsContainer = null;
        this._popover = null;
    }

    didDismissPopover(popover)
    {
        // Remove Evaluate and Probe actions that have no data.
        let emptyActions = this._breakpoint.actions.filter(function(action) {
            if (action.type !== WI.BreakpointAction.Type.Evaluate && action.type !== WI.BreakpointAction.Type.Probe)
                return false;
            return !(action.data && action.data.trim());
        });

        for (let action of emptyActions)
            this._breakpoint.removeAction(action);

        this._breakpoint = null;
    }
};

WI.BreakpointPopoverController.WidePopoverClassName = "wide";
WI.BreakpointPopoverController.HiddenStyleClassName = "hidden";
