/*
 * Copyright (C) 2019 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.
 */

CSSFormatter = class CSSFormatter
{
    constructor(sourceText, builder, indentString = "    ")
    {
        this._success = false;

        this._sourceText = sourceText;

        this._builder = builder;
        if (!this._builder) {
            this._builder = new FormatterContentBuilder(indentString);
            this._builder.setOriginalLineEndings(this._sourceText.lineEndings());
        }

        this._format();

        this._success = true;
    }

    // Public

    get success() { return this._success; }

    get formattedText()
    {
        if (!this._success)
            return null;
        return this._builder.formattedContent;
    }

    get sourceMapData()
    {
        if (!this._success)
            return null;
        return this._builder.sourceMapData;
    }

    // Private

    _format()
    {
        const quoteTypes = new Set([`"`, `'`]);

        const dedentBefore = new Set([`}`]);

        const newlineBefore = new Set([`}`]);
        const newlineAfter = new Set([`{`, `}`, `;`]);

        const indentAfter = new Set([`{`]);

        const addSpaceBefore = new Set([`+`, `*`, `~`, `>`, `(`, `{`, `!`]);
        const addSpaceAfter = new Set([`,`, `+`, `*`, `~`, `>`, `)`, `:`]);

        const removeSpaceBefore = new Set([`,`, `(`, `)`, `}`, `:`, `;`]);
        const removeSpaceAfter = new Set([`(`, `{`, `}`, `,`, `!`, `;`]);

        const whitespaceOnlyRegExp = /^\s*$/;

        const inAtRuleRegExp = /^\s*@[a-zA-Z][-a-zA-Z]+/;
        const inAtRuleBeforeParenthesisRegExp = /^\s*@[a-zA-Z][-a-zA-Z]+$/;
        const inAtRuleAfterParenthesisRegExp = /^\s*@[a-zA-Z][-a-zA-Z]+[^("':]*\([^"':]*:/;
        const inAtSupportsRuleRegExp = /^\s*@[a-zA-Z][-a-zA-Z]+[^"':]*:/;

        const lineStartCouldBePropertyRegExp = /^\s+[-_a-zA-Z][-_a-zA-Z0-9]*/;

        const lastTokenWasOpenParenthesisRegExp = /\(\s*$/;

        let depth = 0;

        for (let i = 0; i < this._sourceText.length; ++i) {
            let c = this._sourceText[i];

            let testCurrentLine = (regExp) => regExp.test(this._builder.currentLine);

            let inComment = false;

            let inSelector = () => {
                let nextOpenBrace = this._sourceText.indexOf(`{`, i);
                if (nextOpenBrace !== -1) {
                    let nextQuote = Infinity;
                    for (let quoteType of quoteTypes) {
                        let quoteIndex = this._sourceText.indexOf(quoteType, i);
                        if (quoteIndex !== -1 && quoteIndex < nextQuote)
                            nextQuote = quoteIndex;
                    }
                    if (nextOpenBrace < nextQuote) {
                        let nextSemicolon = this._sourceText.indexOf(`;`, i);
                        if (nextSemicolon === -1)
                            nextSemicolon = Infinity;

                        let nextNewline = this._sourceText.indexOf(`\n`, i);
                        if (nextNewline === -1)
                            nextNewline = Infinity;

                        if (nextOpenBrace < Math.min(nextSemicolon, nextNewline))
                            return true;
                    }
                }

                if (testCurrentLine(lineStartCouldBePropertyRegExp))
                    return false;

                return true;
            };

            let inProperty = () => {
                if (!depth)
                    return false;
                return !testCurrentLine(inAtRuleRegExp) && !inSelector();
            };

            let formatBefore = () => {
                if (this._builder.lastNewlineAppendWasMultiple && c === `}`)
                    this._builder.removeLastNewline();

                if (dedentBefore.has(c))
                    this._builder.dedent();

                if (!this._builder.lastTokenWasNewline && newlineBefore.has(c))
                    this._builder.appendNewline();

                if (!this._builder.lastTokenWasWhitespace && addSpaceBefore.has(c)) {
                    let shouldAddSpaceBefore = () => {
                        if (c === `(`) {
                            if (testCurrentLine(inAtSupportsRuleRegExp))
                                return false;
                            if (!testCurrentLine(inAtRuleRegExp))
                                return false;
                        }
                        return true;
                    };
                    if (shouldAddSpaceBefore())
                        this._builder.appendSpace();
                }

                while (this._builder.lastTokenWasWhitespace && removeSpaceBefore.has(c)) {
                    let shouldRemoveSpaceBefore = () => {
                        if (c === `:`) {
                            if (!testCurrentLine(this._builder.currentLine.includes(`(`) ? inAtRuleRegExp : inAtRuleBeforeParenthesisRegExp)) {
                                if (!inProperty())
                                    return false;
                            }
                        }
                        if (c === `(`) {
                            if (!testCurrentLine(lastTokenWasOpenParenthesisRegExp)) {
                                if (testCurrentLine(inAtRuleRegExp) && !testCurrentLine(inAtRuleAfterParenthesisRegExp))
                                    return false;
                            }
                        }
                        return true;
                    };
                    if (!shouldRemoveSpaceBefore())
                        break;
                    this._builder.removeLastWhitespace();
                }
            };

            let formatAfter = () => {
                while (this._builder.lastTokenWasWhitespace && removeSpaceAfter.has(c)) {
                    let shouldRemoveSpaceAfter = () => {
                        if (c === `(`) {
                            if (!testCurrentLine(lastTokenWasOpenParenthesisRegExp)) {
                                if (!testCurrentLine(inAtRuleRegExp)) {
                                    if (!inProperty())
                                        return false;
                                }
                            }
                        }
                        return true;
                    };
                    if (!shouldRemoveSpaceAfter())
                        break;
                    this._builder.removeLastWhitespace();
                }

                if (!this._builder.lastTokenWasWhitespace && addSpaceAfter.has(c)) {
                    let shouldAddSpaceAfter = () => {
                        if (c === `:`) {
                            if (!testCurrentLine(this._builder.currentLine.includes(`(`) ? inAtRuleRegExp : inAtRuleBeforeParenthesisRegExp)) {
                                if (!inProperty())
                                    return false;
                            }
                        }
                        if (c === `)`) {
                            if (!testCurrentLine(inAtRuleRegExp)) {
                                if (!inProperty())
                                    return false;
                            }
                        }
                        return true;
                    };
                    if (shouldAddSpaceAfter())
                        this._builder.appendSpace();
                }

                if (indentAfter.has(c))
                    this._builder.indent();

                if (newlineAfter.has(c)) {
                    if (c === `}`)
                        this._builder.appendMultipleNewlines(2);
                    else
                        this._builder.appendNewline();
                }
            };

            let specialSequenceEnd = null;
            if (quoteTypes.has(c))
                specialSequenceEnd = c;
            else if (c === `/` && this._sourceText[i + 1] === `*`) {
                inComment = true;
                specialSequenceEnd = `*/`;
            } else if (c === `u` && this._sourceText[i + 1] === `r` && this._sourceText[i + 2] === `l` && this._sourceText[i + 3] === `(`)
                specialSequenceEnd = `)`;

            if (specialSequenceEnd) {
                let startIndex = i;
                let endIndex = i;
                do {
                    endIndex = this._sourceText.indexOf(specialSequenceEnd, endIndex + specialSequenceEnd.length);
                } while (endIndex !== -1 && !inComment && this._sourceText[endIndex - 1] === `\\`);

                if (endIndex === -1)
                    endIndex = this._sourceText.length;
                endIndex += specialSequenceEnd.length;

                let specialSequenceText = this._sourceText.substring(startIndex, endIndex);

                let lastSourceNewlineWasMultiple = this._sourceText[startIndex - 1] === `\n` && this._sourceText[startIndex - 2] === `\n`;
                let lastAppendNewlineWasMultiple = this._builder.lastNewlineAppendWasMultiple;

                let commentOnOwnLine = false;
                if (inComment) {
                    commentOnOwnLine = testCurrentLine(whitespaceOnlyRegExp);

                    if (!commentOnOwnLine || lastAppendNewlineWasMultiple) {
                        while (this._builder.lastTokenWasNewline)
                            this._builder.removeLastNewline();
                    }

                    if (commentOnOwnLine) {
                        if (startIndex > 0 && !this._builder.indented)
                            this._builder.appendNewline();
                    } else if (this._builder.currentLine.length && !this._builder.lastTokenWasWhitespace)
                        this._builder.appendSpace();

                    if (this._builder.lastTokenWasNewline && lastSourceNewlineWasMultiple)
                        this._builder.appendNewline(true);
                }

                this._builder.appendStringWithPossibleNewlines(specialSequenceText, startIndex);

                i = endIndex;
                c = this._sourceText[i];

                if (inComment) {
                    if (commentOnOwnLine) {
                        if (lastAppendNewlineWasMultiple && !lastSourceNewlineWasMultiple)
                            this._builder.appendMultipleNewlines(2);
                        else
                            this._builder.appendNewline();
                    } else if (!/\s/.test(c)) {
                        if (!testCurrentLine(inAtRuleRegExp) && !inSelector() && !inProperty())
                            this._builder.appendNewline();
                        else
                            this._builder.appendSpace();
                    }
                }

                --i; // Account for the iteration of the for loop.
                c = this._sourceText[i];

                formatAfter();
                continue;
            }

            if (/\s/.test(c)) {
                if (c === `\n`) {
                    if (!this._builder.lastTokenWasNewline) {
                        while (this._builder.lastTokenWasWhitespace)
                            this._builder.removeLastWhitespace();
                        if (!removeSpaceAfter.has(this._builder.lastToken))
                            this._builder.appendNewline();
                        else
                            this._builder.appendSpace();
                    }
                } else if (!this._builder.lastTokenWasWhitespace && !removeSpaceAfter.has(this._builder.lastToken))
                    this._builder.appendSpace();
                continue;
            }

            if (c === `{`)
                ++depth;
            else if (c === `}`)
                --depth;

            formatBefore();
            this._builder.appendToken(c, i);
            formatAfter();
        }

        this._builder.finish();
    }
};
