/*
 * Copyright 2014 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */
#include "GrSKSLPrettyPrint.h"
#include "SkSLString.h"

namespace GrSKSLPrettyPrint {

class GLSLPrettyPrint {
public:
    GLSLPrettyPrint() {}

    SkSL::String prettify(const char** strings, int* lengths, int count, bool countlines) {
        fCountlines = countlines;
        fTabs = 0;
        fLinecount = 1;
        fFreshline = true;

        // If a string breaks while in the middle 'parse until' we need to continue parsing on the
        // next string
        fInParseUntilNewline = false;
        fInParseUntil = false;

        int parensDepth = 0;

        // number 1st line
        this->lineNumbering();
        for (int i = 0; i < count; i++) {
            // setup pretty state
            fIndex = 0;
            fLength = lengths[i];
            fInput = strings[i];

            while (fLength > fIndex) {
                /* the heart and soul of our prettification algorithm.  The rules should hopefully
                 * be self explanatory.  For '#' and '//' tokens we parse until we reach a newline.
                 *
                 * For long style comments like this one, we search for the ending token.  We also
                 * preserve whitespace in these comments WITH THE CAVEAT that we do the newlines
                 * ourselves.  This allows us to remain in control of line numbers, and matching
                 * tabs Existing tabs in the input string are copied over too, but this will look
                 *  funny
                 *
                 * '{' and '}' are handled in basically the same way.  We add a newline if we aren't
                 * on a fresh line, dirty the line, then add a second newline, ie braces are always
                 * on their own lines indented properly.  The one funkiness here is structs print
                 * with the semicolon on its own line.  Its not a problem for a glsl compiler though
                 *
                 * '(' and ')' are basically ignored, except as a sign we need to ignore ';' ala
                 * in for loops.
                 *
                 * ';' means add a new line
                 *
                 * '\t' and '\n' are ignored in general parsing for backwards compatability with
                 * existing shader code and we also have a special case for handling whitespace
                 * at the beginning of fresh lines.
                 *
                 * Otherwise just add the new character to the pretty string, indenting if
                 * necessary.
                 */
                if (fInParseUntilNewline) {
                    this->parseUntilNewline();
                } else if (fInParseUntil) {
                    this->parseUntil(fInParseUntilToken);
                } else if (this->hasToken("#") || this->hasToken("//")) {
                    this->parseUntilNewline();
                } else if (this->hasToken("/*")) {
                    this->parseUntil("*/");
                } else if ('{' == fInput[fIndex]) {
                    this->newline();
                    this->appendChar('{');
                    fTabs++;
                    this->newline();
                } else if ('}' == fInput[fIndex]) {
                    fTabs--;
                    this->newline();
                    this->appendChar('}');
                    this->newline();
                } else if (this->hasToken(")")) {
                    parensDepth--;
                } else if (this->hasToken("(")) {
                    parensDepth++;
                } else if (!parensDepth && this->hasToken(";")) {
                    this->newline();
                } else if ('\t' == fInput[fIndex] || '\n' == fInput[fIndex] ||
                           (fFreshline && ' ' == fInput[fIndex])) {
                    fIndex++;
                } else {
                    this->appendChar(fInput[fIndex]);
                }
            }
        }
        return fPretty;
    }

private:
    void appendChar(char c) {
        this->tabString();
        fPretty.appendf("%c", fInput[fIndex++]);
        fFreshline = false;
    }

    // hasToken automatically consumes the next token, if it is a match, and then tabs
    // if necessary, before inserting the token into the pretty string
    bool hasToken(const char* token) {
        size_t i = fIndex;
        for (size_t j = 0; token[j] && fLength > i; i++, j++) {
            if (token[j] != fInput[i]) {
                return false;
            }
        }
        this->tabString();
        fIndex = i;
        fPretty.append(token);
        fFreshline = false;
        return true;
    }

    void parseUntilNewline() {
        while (fLength > fIndex) {
            if ('\n' == fInput[fIndex]) {
                fIndex++;
                this->newline();
                fInParseUntilNewline = false;
                break;
            }
            fPretty.appendf("%c", fInput[fIndex++]);
            fInParseUntilNewline = true;
        }
    }

    // this code assumes it is not actually searching for a newline.  If you need to search for a
    // newline, then use the function above.  If you do search for a newline with this function
    // it will consume the entire string and the output will certainly not be prettified
    void parseUntil(const char* token) {
        while (fLength > fIndex) {
            // For embedded newlines,  this code will make sure to embed the newline in the
            // pretty string, increase the linecount, and tab out the next line to the appropriate
            // place
            if ('\n' == fInput[fIndex]) {
                this->newline();
                this->tabString();
                fIndex++;
            }
            if (this->hasToken(token)) {
                fInParseUntil = false;
                break;
            }
            fFreshline = false;
            fPretty.appendf("%c", fInput[fIndex++]);
            fInParseUntil = true;
            fInParseUntilToken = token;
        }
    }

    // We only tab if on a newline, otherwise consider the line tabbed
    void tabString() {
        if (fFreshline) {
            for (int t = 0; t < fTabs; t++) {
                fPretty.append("\t");
            }
        }
    }

    // newline is really a request to add a newline, if we are on a fresh line there is no reason
    // to add another newline
    void newline() {
        if (!fFreshline) {
            fFreshline = true;
            fPretty.append("\n");
            this->lineNumbering();
        }
    }

    void lineNumbering() {
        if (fCountlines) {
            fPretty.appendf("%4d\t", fLinecount++);
        }
    }

    bool fCountlines, fFreshline;
    int fTabs, fLinecount;
    size_t fIndex, fLength;
    const char* fInput;
    SkSL::String fPretty;

    // Some helpers for parseUntil when we go over a string length
    bool fInParseUntilNewline;
    bool fInParseUntil;
    const char* fInParseUntilToken;
};

SkSL::String PrettyPrint(const char** strings, int* lengths, int count, bool countlines) {
    GLSLPrettyPrint pp;
    return pp.prettify(strings, lengths, count, countlines);
}

}  // namespace GrSKSLPrettyPrint
