/*
 * 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…"), 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.appendSeparator();
            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 CSS.getSupportedSystemFontFamilyNames.
        // FIXME: Use explicit version checking once https://webkit.org/b/148680 is fixed.
        if (CSSAgent.getSupportedSystemFontFamilyNames) {
            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.Breakpoint.DefaultBreakpointActionType);
        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";
