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

        console.assert(property instanceof WI.CSSProperty);

        this._delegate = delegate || null;
        this._property = property;
        this._element = document.createElement("div");

        this._contentElement = null;
        this._nameElement = null;
        this._valueElement = null;

        this._nameTextField = null;
        this._valueTextField = null;

        this._property.__propertyView = this;

        this._hasInvalidVariableValue = false;

        this._update();
        property.addEventListener(WI.CSSProperty.Event.OverriddenStatusChanged, this.updateStatus, this);
        property.addEventListener(WI.CSSProperty.Event.Changed, this.updateStatus, this);
    }

    // Public

    get element() { return this._element; }
    get nameTextField() { return this._nameTextField; }
    get valueTextField() { return this._valueTextField; }
    get enabled() { return this._property.enabled; }

    set index(index)
    {
        this._element.dataset.propertyIndex = index;
    }

    detached()
    {
        this._property.__propertyView = null;

        if (this._nameTextField)
            this._nameTextField.detached();

        if (this._valueTextField)
            this._valueTextField.detached();
    }

    hidden()
    {
        if (this._nameTextField && this._nameTextField.editing)
            this._nameTextField.element.blur();
        else if (this._valueTextField && this._valueTextField.editing)
            this._valueTextField.element.blur();
    }

    highlight()
    {
        this._element.classList.add("highlighted");
    }

    updateStatus()
    {
        let duplicatePropertyExistsBelow = (cssProperty) => {
            let propertyFound = false;

            for (let property of this._property.ownerStyle.properties) {
                if (property === cssProperty)
                    propertyFound = true;
                else if (property.name === cssProperty.name && propertyFound)
                    return true;
            }

            return false;
        };

        let classNames = [WI.SpreadsheetStyleProperty.StyleClassName];
        let elementTitle = "";

        if (this._property.overridden) {
            classNames.push("overridden");
            if (duplicatePropertyExistsBelow(this._property)) {
                classNames.push("has-warning");
                elementTitle = WI.UIString("Duplicate property");
            }
        }

        if (this._property.implicit)
            classNames.push("implicit");

        if (this._property.ownerStyle.inherited && !this._property.inherited)
            classNames.push("not-inherited");

        if (!this._property.valid && this._property.hasOtherVendorNameOrKeyword())
            classNames.push("other-vendor");
        else if (this._hasInvalidVariableValue || (!this._property.valid && this._property.value !== "")) {
            let propertyNameIsValid = false;
            if (WI.CSSCompletions.cssNameCompletions)
                propertyNameIsValid = WI.CSSCompletions.cssNameCompletions.isValidPropertyName(this._property.name);

            classNames.push("has-warning");

            if (!propertyNameIsValid) {
                classNames.push("invalid-name");
                elementTitle = WI.UIString("Unsupported property name");
            } else {
                classNames.push("invalid-value");
                elementTitle = WI.UIString("Unsupported property value");
            }
        }

        if (!this._property.enabled)
            classNames.push("disabled");

        this._element.className = classNames.join(" ");
        this._element.title = elementTitle;
    }

    applyFilter(filterText)
    {
        let matchesName = this._nameElement.textContent.includes(filterText);
        let matchesValue = this._valueElement.textContent.includes(filterText);
        let matches = matchesName || matchesValue;
        this._contentElement.classList.toggle(WI.GeneralStyleDetailsSidebarPanel.FilterMatchSectionClassName, matches);
        this._contentElement.classList.toggle(WI.GeneralStyleDetailsSidebarPanel.NoFilterMatchInPropertyClassName, !matches);
        return matches;
    }

    // Private

    _remove(replacement = "")
    {
        this.element.remove();

        if (replacement)
            this._property.replaceWithText(replacement);
        else
            this._property.remove();

        this.detached();

        if (this._delegate && typeof this._delegate.spreadsheetStylePropertyRemoved === "function")
            this._delegate.spreadsheetStylePropertyRemoved(this);
    }

    _update()
    {
        this.element.removeChildren();

        if (this._property.editable) {
            this._checkboxElement = this.element.appendChild(document.createElement("input"));
            this._checkboxElement.classList.add("property-toggle");
            this._checkboxElement.type = "checkbox";
            this._checkboxElement.checked = this._property.enabled;
            this._checkboxElement.tabIndex = -1;
            this._checkboxElement.addEventListener("click", (event) => {
                event.stopPropagation();
                let disabled = !this._checkboxElement.checked;
                this._property.commentOut(disabled);
                this._update();
            });
        }

        this._contentElement = this.element.appendChild(document.createElement("span"));
        this._contentElement.className = "content";

        if (!this._property.enabled)
            this._contentElement.append("/* ");

        this._nameElement = this._contentElement.appendChild(document.createElement("span"));
        this._nameElement.classList.add("name");
        this._nameElement.textContent = this._property.name;

        let colonElement = this._contentElement.appendChild(document.createElement("span"));
        colonElement.textContent = ": ";

        this._valueElement = this._contentElement.appendChild(document.createElement("span"));
        this._valueElement.classList.add("value");
        this._renderValue(this._property.rawValue);

        if (this._property.editable && this._property.enabled) {
            this._nameElement.tabIndex = 0;
            this._nameElement.addEventListener("beforeinput", this._handleNameBeforeInput.bind(this));
            this._nameElement.addEventListener("paste", this._handleNamePaste.bind(this));

            this._nameTextField = new WI.SpreadsheetTextField(this, this._nameElement, this._nameCompletionDataProvider.bind(this));

            this._valueElement.tabIndex = 0;
            this._valueElement.addEventListener("beforeinput", this._handleValueBeforeInput.bind(this));

            this._valueTextField = new WI.SpreadsheetTextField(this, this._valueElement, this._valueCompletionDataProvider.bind(this));
        }

        if (this._property.editable) {
            this._setupJumpToSymbol(this._nameElement);
            this._setupJumpToSymbol(this._valueElement);
        }

        let semicolonElement = this._contentElement.appendChild(document.createElement("span"));
        semicolonElement.textContent = ";";

        if (this._property.enabled) {
            this._warningElement = this.element.appendChild(document.createElement("span"));
            this._warningElement.className = "warning";
        } else
            this._contentElement.append(" */");

        this.updateStatus();
    }

    // SpreadsheetTextField delegate

    spreadsheetTextFieldWillStartEditing(textField)
    {
        let isEditingName = textField === this._nameTextField;
        textField.value = isEditingName ? this._property.name : this._property.rawValue;
    }

    spreadsheetTextFieldDidChange(textField)
    {
        if (textField === this._valueTextField)
            this._handleValueChange();
        else if (textField === this._nameTextField)
            this._handleNameChange();
    }

    spreadsheetTextFieldDidCommit(textField, {direction})
    {
        let propertyName = this._nameTextField.value.trim();
        let propertyValue = this._valueTextField.value.trim();
        let willRemoveProperty = false;
        let isEditingName = textField === this._nameTextField;

        if (!propertyName || (!propertyValue && !isEditingName && direction === "forward"))
            willRemoveProperty = true;

        if (!isEditingName && !willRemoveProperty)
            this._renderValue(propertyValue);

        if (direction === "forward") {
            if (isEditingName && !willRemoveProperty) {
                // Move focus from the name to the value.
                this._valueTextField.startEditing();
                return;
            }
        } else {
            if (!isEditingName) {
                // Move focus from the value to the name.
                this._nameTextField.startEditing();
                return;
            }
        }

        if (typeof this._delegate.spreadsheetStylePropertyFocusMoved === "function") {
            // Move focus away from the current property, to the next or previous one, if exists, or to the next or previous rule, if exists.
            this._delegate.spreadsheetStylePropertyFocusMoved(this, {direction, willRemoveProperty});
        }

        if (willRemoveProperty)
            this._remove();
    }

    spreadsheetTextFieldDidBlur(textField, event)
    {
        let focusedOutsideThisProperty = event.relatedTarget !== this._nameElement && event.relatedTarget !== this._valueElement;
        if (focusedOutsideThisProperty && (!this._nameTextField.value.trim() || !this._valueTextField.value.trim())) {
            this._remove();
            return;
        }

        if (textField === this._valueTextField)
            this._renderValue(this._valueElement.textContent);
    }

    spreadsheetTextFieldDidBackspace(textField)
    {
        if (textField === this._nameTextField)
            this.spreadsheetTextFieldDidCommit(textField, {direction: "backward"});
        else if (textField === this._valueTextField)
            this._nameTextField.startEditing();
    }

    // Private

    _renderValue(value)
    {
        this._hasInvalidVariableValue = false;

        const maxValueLength = 150;
        let tokens = WI.tokenizeCSSValue(value);

        if (this._property.enabled) {
            // FIXME: <https://webkit.org/b/178636> Web Inspector: Styles: Make inline widgets work with CSS functions (var(), calc(), etc.)
            tokens = this._addGradientTokens(tokens);
            tokens = this._addColorTokens(tokens);
            tokens = this._addTimingFunctionTokens(tokens, "cubic-bezier");
            tokens = this._addTimingFunctionTokens(tokens, "spring");
            tokens = this._addVariableTokens(tokens);
        }

        tokens = tokens.map((token) => {
            if (token instanceof Element)
                return token;

            let className = "";

            if (token.type) {
                if (token.type.includes("string"))
                    className = "token-string";
                else if (token.type.includes("link"))
                    className = "token-link";
                else if (token.type.includes("comment"))
                    className = "token-comment";
            }

            if (className) {
                let span = document.createElement("span");
                span.classList.add(className);
                span.textContent = token.value.truncateMiddle(maxValueLength);
                return span;
            }

            return token.value;
        });

        this._valueElement.removeChildren();
        this._valueElement.append(...tokens);
    }

    _createInlineSwatch(type, text, valueObject)
    {
        let tokenElement = document.createElement("span");
        let innerElement = document.createElement("span");
        innerElement.textContent = text;

        let readOnly = !this._property.editable;
        let swatch = new WI.InlineSwatch(type, valueObject, readOnly);

        swatch.addEventListener(WI.InlineSwatch.Event.ValueChanged, (event) => {
            let value = event.data.value && event.data.value.toString();
            if (!value)
                return;

            innerElement.textContent = value;
            this._handleValueChange();
        }, this);

        if (typeof this._delegate.stylePropertyInlineSwatchActivated === "function") {
            swatch.addEventListener(WI.InlineSwatch.Event.Activated, () => {
                this._delegate.stylePropertyInlineSwatchActivated();
            });
        }

        if (typeof this._delegate.stylePropertyInlineSwatchDeactivated === "function") {
            swatch.addEventListener(WI.InlineSwatch.Event.Deactivated, () => {
                this._delegate.stylePropertyInlineSwatchDeactivated();
            });
        }

        tokenElement.append(swatch.element, innerElement);

        // Prevent the value from editing when clicking on the swatch.
        swatch.element.addEventListener("mousedown", (event) => { event.stop(); });

        return tokenElement;
    }

    _addGradientTokens(tokens)
    {
        let gradientRegex = /^(repeating-)?(linear|radial)-gradient$/i;
        let newTokens = [];
        let gradientStartIndex = NaN;
        let openParenthesis = 0;

        for (let i = 0; i < tokens.length; i++) {
            let token = tokens[i];
            if (token.type && token.type.includes("atom") && gradientRegex.test(token.value)) {
                gradientStartIndex = i;
                openParenthesis = 0;
            } else if (token.value === "(" && !isNaN(gradientStartIndex))
                openParenthesis++;
            else if (token.value === ")" && !isNaN(gradientStartIndex)) {
                openParenthesis--;
                if (openParenthesis > 0) {
                    // Matched a CSS function inside of the gradient.
                    continue;
                }

                let rawTokens = tokens.slice(gradientStartIndex, i + 1);
                let text = rawTokens.map((token) => token.value).join("");
                let gradient = WI.Gradient.fromString(text);
                if (gradient)
                    newTokens.push(this._createInlineSwatch(WI.InlineSwatch.Type.Gradient, text, gradient));
                else
                    newTokens.push(...rawTokens);

                gradientStartIndex = NaN;
            } else if (isNaN(gradientStartIndex))
                newTokens.push(token);
        }

        return newTokens;
    }

    _addColorTokens(tokens)
    {
        let newTokens = [];

        let pushPossibleColorToken = (text, ...rawTokens) => {
            let color = WI.Color.fromString(text);
            if (color)
                newTokens.push(this._createInlineSwatch(WI.InlineSwatch.Type.Color, text, color));
            else
                newTokens.push(...rawTokens);
        };

        let colorFunctionStartIndex = NaN;

        for (let i = 0; i < tokens.length; i++) {
            let token = tokens[i];
            if (token.type && token.type.includes("hex-color")) {
                // Hex
                pushPossibleColorToken(token.value, token);
            } else if (WI.Color.FunctionNames.has(token.value) && token.type && (token.type.includes("atom") || token.type.includes("keyword"))) {
                // Color Function start
                colorFunctionStartIndex = i;
            } else if (isNaN(colorFunctionStartIndex) && token.type && token.type.includes("keyword")) {
                // Color keyword
                pushPossibleColorToken(token.value, token);
            } else if (!isNaN(colorFunctionStartIndex)) {
                // Color Function end
                if (token.value !== ")")
                    continue;

                let rawTokens = tokens.slice(colorFunctionStartIndex, i + 1);
                let text = rawTokens.map((token) => token.value).join("");
                pushPossibleColorToken(text, ...rawTokens);
                colorFunctionStartIndex = NaN;
            } else
                newTokens.push(token);
        }

        return newTokens;
    }

    _addTimingFunctionTokens(tokens, tokenType)
    {
        let newTokens = [];
        let startIndex = NaN;
        let openParenthesis = 0;

        for (let i = 0; i < tokens.length; i++) {
            let token = tokens[i];
            if (token.value === tokenType && token.type && token.type.includes("atom")) {
                startIndex = i;
                openParenthesis = 0;
            } else if (token.value === "(" && !isNaN(startIndex))
                openParenthesis++;
            else if (token.value === ")" && !isNaN(startIndex)) {

                openParenthesis--;
                if (openParenthesis > 0)
                    continue;

                let rawTokens = tokens.slice(startIndex, i + 1);
                let text = rawTokens.map((token) => token.value).join("");

                let valueObject;
                let inlineSwatchType;
                if (tokenType === "cubic-bezier") {
                    valueObject = WI.CubicBezier.fromString(text);
                    inlineSwatchType = WI.InlineSwatch.Type.Bezier;
                } else if (tokenType === "spring") {
                    valueObject = WI.Spring.fromString(text);
                    inlineSwatchType = WI.InlineSwatch.Type.Spring;
                }

                if (valueObject)
                    newTokens.push(this._createInlineSwatch(inlineSwatchType, text, valueObject));
                else
                    newTokens.push(...rawTokens);

                startIndex = NaN;
            } else if (isNaN(startIndex))
                newTokens.push(token);
        }

        return newTokens;
    }

    _addVariableTokens(tokens)
    {
        let newTokens = [];
        let startIndex = NaN;
        let openParenthesis = 0;

        for (let i = 0; i < tokens.length; i++) {
            let token = tokens[i];
            if (token.value === "var" && token.type && token.type.includes("atom")) {
                startIndex = i;
                openParenthesis = 0;
            } else if (token.value === "(" && !isNaN(startIndex))
                ++openParenthesis;
            else if (token.value === ")" && !isNaN(startIndex)) {
                --openParenthesis;
                if (openParenthesis > 0)
                    continue;

                let rawTokens = tokens.slice(startIndex, i + 1);
                let tokenValues = rawTokens.map((token) => token.value);
                let variableName = tokenValues.find((value, i) => value.startsWith("--") && /\bvariable-2\b/.test(rawTokens[i].type));

                const dontCreateIfMissing = true;
                let variableProperty = this._property.ownerStyle.nodeStyles.computedStyle.propertyForName(variableName, dontCreateIfMissing);
                if (variableProperty) {
                    let valueObject = variableProperty.value.trim();
                    newTokens.push(this._createInlineSwatch(WI.InlineSwatch.Type.Variable, tokenValues.join(""), valueObject));
                } else {
                    this._hasInvalidVariableValue = true;
                    newTokens.push(...rawTokens);
                }

                startIndex = NaN;
            } else if (isNaN(startIndex))
                newTokens.push(token);
        }

        return newTokens;
    }

    _handleNameChange()
    {
        this._property.name = this._nameElement.textContent.trim();
    }

    _handleValueChange()
    {
        this._property.rawValue = this._valueElement.textContent.trim();
    }

    _handleNameBeforeInput(event)
    {
        if (event.data !== ":" || event.inputType !== "insertText")
            return;

        event.preventDefault();
        this._nameTextField.discardCompletion();
        this._valueTextField.startEditing();
    }

    _handleNamePaste(event)
    {
        let text = event.clipboardData.getData("text/plain");
        if (!text || !text.includes(":"))
            return;

        event.preventDefault();

        this._remove(text);

        if (this._delegate.spreadsheetStylePropertyAddBlankPropertySoon) {
            this._delegate.spreadsheetStylePropertyAddBlankPropertySoon(this, {
                index: parseInt(this._element.dataset.propertyIndex) + 1,
            });
        }
    }

    _nameCompletionDataProvider(prefix)
    {
        return WI.CSSCompletions.cssNameCompletions.startsWith(prefix);
    }

    _handleValueBeforeInput(event)
    {
        if (event.data !== ";" || event.inputType !== "insertText")
            return;

        let text = this._valueTextField.valueWithoutSuggestion();
        let selection = window.getSelection();
        if (!selection.rangeCount || selection.getRangeAt(0).endOffset !== text.length)
            return;

        // Find the first and last index (if any) of a quote character to ensure that the string
        // doesn't contain unbalanced quotes. If so, then there's no way that the semicolon could be
        // part of a string within the value, so we can assume that it's the property "terminator".
        const quoteRegex = /["']/g;
        let start = -1;
        let end = text.length;
        let match = null;
        while (match = quoteRegex.exec(text)) {
            if (start < 0)
                start = match.index;
            end = match.index + 1;
        }

        if (start !== -1 && !text.substring(start, end).hasMatchingEscapedQuotes())
            return;

        event.preventDefault();
        this._valueTextField.stopEditing();
        this.spreadsheetTextFieldDidCommit(this._valueTextField, {direction: "forward"});
    }

    _valueCompletionDataProvider(prefix)
    {
        let propertyName = this._nameElement.textContent.trim();
        return WI.CSSKeywordCompletions.forProperty(propertyName).startsWith(prefix);
    }

    _setupJumpToSymbol(element)
    {
        element.addEventListener("mousedown", (event) => {
            if (event.button !== 0)
                return;

            if (!WI.modifierKeys.metaKey)
                return;

            if (element.isContentEditable)
                return;

            let sourceCodeLocation = null;
            if (this._property.ownerStyle.ownerRule)
                sourceCodeLocation = this._property.ownerStyle.ownerRule.sourceCodeLocation;

            if (!sourceCodeLocation)
                return;

            let range = this._property.styleSheetTextRange;
            const options = {
                ignoreNetworkTab: true,
                ignoreSearchTab: true,
            };
            let sourceCode = sourceCodeLocation.sourceCode;
            WI.showSourceCodeLocation(sourceCode.createSourceCodeLocation(range.startLine, range.startColumn), options);
        });
    }
};

WI.SpreadsheetStyleProperty.StyleClassName = "property";
