#include "SqlSyntaxHighlighter.h"

#include "catalog/PgTypeContainer.h"
#include "SqlLexer.h"
#include "util/Colors.h"



SqlSyntaxHighlighter::SqlSyntaxHighlighter(QTextDocument *parent)
	: QSyntaxHighlighter(parent)
{
    const ColorTheme& theme = GetColorTheme();

    m_keywordFormat.setForeground(theme.keyword);
    m_keywordFormat.setFontWeight(QFont::Bold);

    m_commentFormat.setForeground(theme.comment);

    m_quotedStringFormat.setForeground(theme.quotedString);

    m_quotedIdentifierFormat.setForeground(theme.quotedIdentifier);

    m_typeFormat.setForeground(theme.type);
	m_typeFormat.setFontWeight(QFont::Bold);
    
    m_parameterFormat.setForeground(theme.parameter);
    m_parameterFormat.setFontWeight(QFont::Bold);
}

SqlSyntaxHighlighter::~SqlSyntaxHighlighter()
{
}

void SqlSyntaxHighlighter::setTypes(const PgTypeContainer& types)
{
	m_typeNames.clear();
	for (auto&& e : types) {
		m_typeNames.insert(e.objectName());
	}
	rehighlight();
}

void SqlSyntaxHighlighter::highlightBlock(const QString &text)
{
	int previous_state = previousBlockState();
	if (previous_state <= 0)
		previous_state = 0;
	SqlLexer lexer(text, (LexerState)previous_state);
	int startpos, length;
	BasicTokenType tokentype;
	QString s;
	while (lexer.nextBasicToken(startpos, length, tokentype, s) && tokentype != BasicTokenType::End) {
		switch (tokentype) {
		case BasicTokenType::None:
		case BasicTokenType::End: // End of input
		case BasicTokenType::DollarQuote:
			break;
		case BasicTokenType::Symbol: { // can be many things, keyword, object name, operator, ..
				auto kw = getPgsqlKeyword(s);
				if (kw != nullptr) {
					setFormat(startpos, length, m_keywordFormat);
				}
				else if (m_typeNames.count(s.toLower()) > 0) {
					setFormat(startpos, length, m_typeFormat);
				}
			}
			break;
		case BasicTokenType::OpenBlockComment:
			setCurrentBlockState((int)lexer.currentState());
		case BasicTokenType::BlockComment:
		case BasicTokenType::Comment:
			setFormat(startpos, length, m_commentFormat);
			break;
		case BasicTokenType::QuotedString:
			setFormat(startpos, length, m_quotedStringFormat);
			break;
		case BasicTokenType::QuotedIdentifier:
			setFormat(startpos, length, m_quotedIdentifierFormat);
			break;
		case BasicTokenType::Parameter:
            setFormat(startpos, length, m_parameterFormat);
            break;
		}
	}
}
