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

        console.assert(codeMirror);

        this._codeMirror = codeMirror;
        this._delegate = delegate || null;
        this._mode = WI.CodeMirrorTokenTrackingController.Mode.None;

        this._mouseOverDelayDuration = 0;
        this._mouseOutReleaseDelayDuration = 0;
        this._classNameForHighlightedRange = null;

        this._enabled = false;
        this._tracking = false;
        this._previousTokenInfo = null;
        this._hoveredMarker = null;
        this._ignoreNextMouseMove = false;

        const hidePopover = this._hidePopover.bind(this);

        this._codeMirror.addKeyMap({
            "Cmd-Enter": this._handleCommandEnterKey.bind(this),
            "Esc": hidePopover
        });

        this._codeMirror.on("cursorActivity", hidePopover);
    }

    // Public

    get delegate()
    {
        return this._delegate;
    }

    set delegate(x)
    {
        this._delegate = x;
    }

    get enabled()
    {
        return this._enabled;
    }

    set enabled(enabled)
    {
        if (this._enabled === enabled)
            return;

        this._enabled = enabled;

        var wrapper = this._codeMirror.getWrapperElement();
        if (enabled) {
            wrapper.addEventListener("mouseenter", this);
            wrapper.addEventListener("mouseleave", this);
            this._updateHoveredTokenInfo({left: WI.mouseCoords.x, top: WI.mouseCoords.y});
            this._startTracking();
        } else {
            wrapper.removeEventListener("mouseenter", this);
            wrapper.removeEventListener("mouseleave", this);
            this._stopTracking();
        }
    }

    get mode()
    {
        return this._mode;
    }

    set mode(mode)
    {
        var oldMode = this._mode;

        this._mode = mode || WI.CodeMirrorTokenTrackingController.Mode.None;

        if (oldMode !== this._mode && this._tracking && this._previousTokenInfo)
            this._processNewHoveredToken(this._previousTokenInfo);
    }

    get mouseOverDelayDuration()
    {
        return this._mouseOverDelayDuration;
    }

    set mouseOverDelayDuration(x)
    {
        console.assert(x >= 0);
        this._mouseOverDelayDuration = Math.max(x, 0);
    }

    get mouseOutReleaseDelayDuration()
    {
        return this._mouseOutReleaseDelayDuration;
    }

    set mouseOutReleaseDelayDuration(x)
    {
        console.assert(x >= 0);
        this._mouseOutReleaseDelayDuration = Math.max(x, 0);
    }

    get classNameForHighlightedRange()
    {
        return this._classNameForHighlightedRange;
    }

    set classNameForHighlightedRange(x)
    {
        this._classNameForHighlightedRange = x || null;
    }

    get candidate()
    {
        return this._candidate;
    }

    get hoveredMarker()
    {
        return this._hoveredMarker;
    }

    set hoveredMarker(hoveredMarker)
    {
        this._hoveredMarker = hoveredMarker;
    }

    highlightLastHoveredRange()
    {
        if (this._candidate)
            this.highlightRange(this._candidate.hoveredTokenRange);
    }

    highlightRange(range)
    {
        // Nothing to do if we're trying to highlight the same range.
        if (this._codeMirrorMarkedText && this._codeMirrorMarkedText.className === this._classNameForHighlightedRange) {
            var highlightedRange = this._codeMirrorMarkedText.find();
            if (!highlightedRange)
                return;
            if (WI.compareCodeMirrorPositions(highlightedRange.from, range.start) === 0 &&
                WI.compareCodeMirrorPositions(highlightedRange.to, range.end) === 0)
                return;
        }

        this.removeHighlightedRange();

        var className = this._classNameForHighlightedRange || "";
        this._codeMirrorMarkedText = this._codeMirror.markText(range.start, range.end, {className});

        window.addEventListener("mousemove", this, true);
    }

    removeHighlightedRange()
    {
        if (!this._codeMirrorMarkedText)
            return;

        this._codeMirrorMarkedText.clear();
        this._codeMirrorMarkedText = null;

        window.removeEventListener("mousemove", this, true);
    }

    // Private

    _startTracking()
    {
        if (this._tracking)
            return;

        this._tracking = true;
        this._ignoreNextMouseMove = false;

        var wrapper = this._codeMirror.getWrapperElement();
        wrapper.addEventListener("mousemove", this, true);
        wrapper.addEventListener("mouseout", this, false);
        wrapper.addEventListener("mousedown", this, false);
        wrapper.addEventListener("mouseup", this, false);
        wrapper.addEventListener("mousewheel", this, false);
        window.addEventListener("blur", this, true);
    }

    _stopTracking()
    {
        if (!this._tracking)
            return;

        this._tracking = false;
        this._candidate = null;

        var wrapper = this._codeMirror.getWrapperElement();
        wrapper.removeEventListener("mousemove", this, true);
        wrapper.removeEventListener("mouseout", this, false);
        wrapper.removeEventListener("mousedown", this, false);
        wrapper.removeEventListener("mouseup", this, false);
        wrapper.removeEventListener("mousewheel", this, false);
        window.removeEventListener("blur", this, true);
        window.removeEventListener("mousemove", this, true);

        this._resetTrackingStates();
    }

    handleEvent(event)
    {
        switch (event.type) {
        case "mouseenter":
            this._mouseEntered(event);
            break;
        case "mouseleave":
            this._mouseLeft(event);
            break;
        case "mousemove":
            if (event.currentTarget === window)
                this._mouseMovedWithMarkedText(event);
            else
                this._mouseMovedOverEditor(event);
            break;
        case "mouseout":
            // Only deal with a mouseout event that has the editor wrapper as the target.
            if (!event.currentTarget.contains(event.relatedTarget))
                this._mouseMovedOutOfEditor(event);
            break;
        case "mousedown":
            this._mouseButtonWasPressedOverEditor(event);
            break;
        case "mouseup":
            this._mouseButtonWasReleasedOverEditor(event);
            break;
        case "mousewheel":
            this._ignoreNextMouseMove = true;
            break;
        case "blur":
            this._windowLostFocus(event);
            break;
        }
    }

    _handleCommandEnterKey(codeMirror)
    {
        const tokenInfo = this._getTokenInfoForPosition(codeMirror.getCursor("head"));
        tokenInfo.triggeredBy = WI.CodeMirrorTokenTrackingController.TriggeredBy.Keyboard;
        this._processNewHoveredToken(tokenInfo);
    }

    _hidePopover()
    {
        if (!this._candidate)
            return CodeMirror.Pass;

        if (this._delegate && typeof this._delegate.tokenTrackingControllerHighlightedRangeReleased === "function") {
            const forceHidePopover = true;
            this._delegate.tokenTrackingControllerHighlightedRangeReleased(this, forceHidePopover);
        }
    }

    _mouseEntered(event)
    {
        if (!this._tracking)
            this._startTracking();
    }

    _mouseLeft(event)
    {
        this._stopTracking();
    }

    _mouseMovedWithMarkedText(event)
    {
        if (this._candidate && this._candidate.triggeredBy === WI.CodeMirrorTokenTrackingController.TriggeredBy.Keyboard)
            return;

        var shouldRelease = !event.target.classList.contains(this._classNameForHighlightedRange);
        if (shouldRelease && this._delegate && typeof this._delegate.tokenTrackingControllerCanReleaseHighlightedRange === "function")
            shouldRelease = this._delegate.tokenTrackingControllerCanReleaseHighlightedRange(this, event.target);

        if (shouldRelease) {
            if (!this._markedTextMouseoutTimer)
                this._markedTextMouseoutTimer = setTimeout(this._markedTextIsNoLongerHovered.bind(this), this._mouseOutReleaseDelayDuration);
            return;
        }

        if (this._markedTextMouseoutTimer)
            clearTimeout(this._markedTextMouseoutTimer);

        this._markedTextMouseoutTimer = 0;
    }

    _markedTextIsNoLongerHovered()
    {
        if (this._delegate && typeof this._delegate.tokenTrackingControllerHighlightedRangeReleased === "function")
            this._delegate.tokenTrackingControllerHighlightedRangeReleased(this);

        this._markedTextMouseoutTimer = 0;
    }

    _mouseMovedOverEditor(event)
    {
        if (this._ignoreNextMouseMove) {
            this._ignoreNextMouseMove = false;
            return;
        }

        this._updateHoveredTokenInfo({left: event.pageX, top: event.pageY});
    }

    _updateHoveredTokenInfo(mouseCoords)
    {
        // Get the position in the text and the token at that position.
        var position = this._codeMirror.coordsChar(mouseCoords);
        var token = this._codeMirror.getTokenAt(position);

        if (!token || !token.type || !token.string) {
            if (this._hoveredMarker && this._delegate && typeof this._delegate.tokenTrackingControllerMouseOutOfHoveredMarker === "function") {
                if (!this._codeMirror.findMarksAt(position).includes(this._hoveredMarker.codeMirrorTextMarker))
                    this._delegate.tokenTrackingControllerMouseOutOfHoveredMarker(this, this._hoveredMarker);
            }

            this._resetTrackingStates();
            return;
        }

        // Stop right here if we're hovering the same token as we were last time.
        if (this._previousTokenInfo &&
            this._previousTokenInfo.position.line === position.line &&
            this._previousTokenInfo.token.start === token.start &&
            this._previousTokenInfo.token.end === token.end)
            return;

        // We have a new hovered token.
        var tokenInfo = this._previousTokenInfo = this._getTokenInfoForPosition(position);

        if (/\bmeta\b/.test(token.type)) {
            let nextTokenPosition = Object.shallowCopy(position);
            nextTokenPosition.ch = tokenInfo.token.end + 1;

            let nextToken = this._codeMirror.getTokenAt(nextTokenPosition);
            if (nextToken && nextToken.type && !/\bmeta\b/.test(nextToken.type)) {
                console.assert(tokenInfo.token.end === nextToken.start);

                tokenInfo.token.type = nextToken.type;
                tokenInfo.token.string = tokenInfo.token.string + nextToken.string;
                tokenInfo.token.end = nextToken.end;
            }
        } else {
            let previousTokenPosition = Object.shallowCopy(position);
            previousTokenPosition.ch = tokenInfo.token.start - 1;

            let previousToken = this._codeMirror.getTokenAt(previousTokenPosition);
            if (previousToken && previousToken.type && /\bmeta\b/.test(previousToken.type)) {
                console.assert(tokenInfo.token.start === previousToken.end);

                tokenInfo.token.string = previousToken.string + tokenInfo.token.string;
                tokenInfo.token.start = previousToken.start;
            }
        }

        if (this._tokenHoverTimer)
            clearTimeout(this._tokenHoverTimer);

        this._tokenHoverTimer = 0;

        if (this._codeMirrorMarkedText || !this._mouseOverDelayDuration)
            this._processNewHoveredToken(tokenInfo);
        else
            this._tokenHoverTimer = setTimeout(this._processNewHoveredToken.bind(this, tokenInfo), this._mouseOverDelayDuration);
    }

    _getTokenInfoForPosition(position)
    {
        var token = this._codeMirror.getTokenAt(position);
        var innerMode = CodeMirror.innerMode(this._codeMirror.getMode(), token.state);
        var codeMirrorModeName = innerMode.mode.alternateName || innerMode.mode.name;
        return {
            token,
            position,
            innerMode,
            modeName: codeMirrorModeName
        };
    }

    _mouseMovedOutOfEditor(event)
    {
        if (this._tokenHoverTimer)
            clearTimeout(this._tokenHoverTimer);

        this._tokenHoverTimer = 0;
        this._previousTokenInfo = null;
        this._selectionMayBeInProgress = false;
    }

    _mouseButtonWasPressedOverEditor(event)
    {
        this._selectionMayBeInProgress = true;
    }

    _mouseButtonWasReleasedOverEditor(event)
    {
        this._selectionMayBeInProgress = false;
        this._mouseMovedOverEditor(event);

        if (this._codeMirrorMarkedText && this._previousTokenInfo) {
            var position = this._codeMirror.coordsChar({left: event.pageX, top: event.pageY});
            var marks = this._codeMirror.findMarksAt(position);
            for (var i = 0; i < marks.length; ++i) {
                if (marks[i] === this._codeMirrorMarkedText) {
                    if (this._delegate && typeof this._delegate.tokenTrackingControllerHighlightedRangeWasClicked === "function")
                        this._delegate.tokenTrackingControllerHighlightedRangeWasClicked(this);

                    break;
                }
            }
        }
    }

    _windowLostFocus(event)
    {
        this._resetTrackingStates();
    }

    _processNewHoveredToken(tokenInfo)
    {
        console.assert(tokenInfo);

        if (this._selectionMayBeInProgress)
            return;

        this._candidate = null;

        switch (this._mode) {
        case WI.CodeMirrorTokenTrackingController.Mode.NonSymbolTokens:
            this._candidate = this._processNonSymbolToken(tokenInfo);
            break;
        case WI.CodeMirrorTokenTrackingController.Mode.JavaScriptExpression:
        case WI.CodeMirrorTokenTrackingController.Mode.JavaScriptTypeInformation:
            this._candidate = this._processJavaScriptExpression(tokenInfo);
            break;
        case WI.CodeMirrorTokenTrackingController.Mode.MarkedTokens:
            this._candidate = this._processMarkedToken(tokenInfo);
            break;
        }

        if (!this._candidate)
            return;

        this._candidate.triggeredBy = tokenInfo.triggeredBy;

        if (this._markedTextMouseoutTimer)
            clearTimeout(this._markedTextMouseoutTimer);

        this._markedTextMouseoutTimer = 0;

        if (this._delegate && typeof this._delegate.tokenTrackingControllerNewHighlightCandidate === "function")
            this._delegate.tokenTrackingControllerNewHighlightCandidate(this, this._candidate);
    }

    _processNonSymbolToken(tokenInfo)
    {
        // Ignore any symbol tokens.
        var type = tokenInfo.token.type;
        if (!type)
            return null;

        var startPosition = {line: tokenInfo.position.line, ch: tokenInfo.token.start};
        var endPosition = {line: tokenInfo.position.line, ch: tokenInfo.token.end};

        return {
            hoveredToken: tokenInfo.token,
            hoveredTokenRange: {start: startPosition, end: endPosition},
        };
    }

    _processJavaScriptExpression(tokenInfo)
    {
        // Only valid within JavaScript.
        if (tokenInfo.modeName !== "javascript")
            return null;

        var startPosition = {line: tokenInfo.position.line, ch: tokenInfo.token.start};
        var endPosition = {line: tokenInfo.position.line, ch: tokenInfo.token.end};

        function tokenIsInRange(token, range)
        {
            return token.line >= range.start.line && token.ch >= range.start.ch &&
                   token.line <= range.end.line && token.ch <= range.end.ch;
        }

        // If the hovered token is within a selection, use the selection as our expression.
        if (this._codeMirror.somethingSelected()) {
            var selectionRange = {
                start: this._codeMirror.getCursor("start"),
                end: this._codeMirror.getCursor("end")
            };

            if (tokenIsInRange(startPosition, selectionRange) || tokenIsInRange(endPosition, selectionRange)) {
                return {
                    hoveredToken: tokenInfo.token,
                    hoveredTokenRange: selectionRange,
                    expression: this._codeMirror.getSelection(),
                    expressionRange: selectionRange,
                };
            }
        }

        // We only handle vars, definitions, properties, and the keyword 'this'.
        var type = tokenInfo.token.type;
        var isProperty = type.indexOf("property") !== -1;
        var isKeyword = type.indexOf("keyword") !== -1;
        if (!isProperty && !isKeyword && type.indexOf("variable") === -1 && type.indexOf("def") === -1)
            return null;

        // Not object literal property names, but yes if an object literal shorthand property, which is a variable.
        let state = tokenInfo.innerMode.state;
        if (isProperty && state.lexical && state.lexical.type === "}") {
            // Peek ahead to see if the next token is "}" or ",". If it is, we are a shorthand and therefore a variable.
            let shorthand = false;
            let mode = tokenInfo.innerMode.mode;
            let position = {line: tokenInfo.position.line, ch: tokenInfo.token.end};
            WI.walkTokens(this._codeMirror, mode, position, function(tokenType, string) {
                if (tokenType)
                    return false;
                if (string === "(")
                    return false;
                if (string === "," || string === "}") {
                    shorthand = true;
                    return false;
                }
                return true;
            });

            if (!shorthand)
                return null;
        }

        // Only the "this" keyword.
        if (isKeyword && tokenInfo.token.string !== "this")
            return null;

        // Work out the full hovered expression.
        var expression = tokenInfo.token.string;
        var expressionStartPosition = {line: tokenInfo.position.line, ch: tokenInfo.token.start};
        while (true) {
            var token = this._codeMirror.getTokenAt(expressionStartPosition);
            if (!token)
                break;

            var isDot = !token.type && token.string === ".";
            var isExpression = token.type && token.type.includes("m-javascript");
            if (!isDot && !isExpression)
                break;

            if (isExpression) {
                // Disallow operators. We want the hovered expression to be just a single operand.
                // Also, some operators can modify values, such as pre-increment and assignment operators.
                if (token.type.includes("operator"))
                    break;

                // Don't break out of a template string quasi group.
                if (token.type.includes("string-2"))
                    break;
            }

            expression = token.string + expression;
            expressionStartPosition.ch = token.start;
        }

        // Return the candidate for this token and expression.
        return {
            hoveredToken: tokenInfo.token,
            hoveredTokenRange: {start: startPosition, end: endPosition},
            expression,
            expressionRange: {start: expressionStartPosition, end: endPosition},
        };
    }

    _processMarkedToken(tokenInfo)
    {
        return this._processNonSymbolToken(tokenInfo);
    }

    _resetTrackingStates()
    {
        if (this._tokenHoverTimer)
            clearTimeout(this._tokenHoverTimer);

        this._tokenHoverTimer = 0;

        this._selectionMayBeInProgress = false;
        this._previousTokenInfo = null;
        this.removeHighlightedRange();
    }
};

WI.CodeMirrorTokenTrackingController.JumpToSymbolHighlightStyleClassName = "jump-to-symbol-highlight";

WI.CodeMirrorTokenTrackingController.Mode = {
    None: "none",
    NonSymbolTokens: "non-symbol-tokens",
    JavaScriptExpression: "javascript-expression",
    JavaScriptTypeInformation: "javascript-type-information",
    MarkedTokens: "marked-tokens"
};

WI.CodeMirrorTokenTrackingController.TriggeredBy = {
    Keyboard: "keyboard",
    Hover: "hover"
};
