package consulo.javaee.jsp.lexer;

import com.intellij.lexer.JavaLexer;
import com.intellij.lexer.Lexer;
import com.intellij.lexer.LexerPosition;
import com.intellij.lexer.LookAheadLexer;
import com.intellij.pom.java.LanguageLevel;
import com.intellij.psi.JavaTokenType;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.tree.java.IJavaElementType;

/**
 * @author VISTALL
 * @since 23-May-17
 */
public class _JspJavaLexer extends LookAheadLexer
{
	public static final IElementType JSP_IN_JAVA = new IJavaElementType("JSP_IN_JAVA");

	private boolean myEnabledJavaTokens;

	public _JspJavaLexer()
	{
		super(new JavaLexer(LanguageLevel.HIGHEST));
	}

	@Override
	protected void lookAhead(Lexer baseLexer)
	{
		IElementType tokenType = baseLexer.getTokenType();
		if(tokenType == null)
		{
			super.lookAhead(baseLexer);
			return;
		}

		if(myEnabledJavaTokens)
		{
			if(tokenType == JavaTokenType.PERC)
			{
				LexerPosition currentPosition = baseLexer.getCurrentPosition();

				boolean tagClosed = false;
				baseLexer.advance();

				if(baseLexer.getTokenType() == JavaTokenType.GT)
				{
					tagClosed = true;
				}
				baseLexer.restore(currentPosition);

				if(tagClosed)
				{
					myEnabledJavaTokens = false;
					baseLexer.advance();
					baseLexer.advance();
					addToken(JSP_IN_JAVA);
					return;
				}
			}

			super.lookAhead(baseLexer);
			return;
		}

		if(tokenType == JavaTokenType.LT)
		{
			LexerPosition currentPosition = baseLexer.getCurrentPosition();

			// this <
			baseLexer.advance();

			// <%
			IElementType token2 = baseLexer.getTokenType();
			if(token2 == JavaTokenType.PERC)
			{
				baseLexer.advance();

				// simple <%
				if(baseLexer.getTokenType() == JavaTokenType.WHITE_SPACE)
				{
					baseLexer.restore(currentPosition);

					baseLexer.advance(); // <
					baseLexer.advance(); // %
					addToken(JSP_IN_JAVA);
					myEnabledJavaTokens = true;
					return;
				}
				// <%!
				else if(baseLexer.getTokenType() == JavaTokenType.EXCL || baseLexer.getTokenType() == JavaTokenType.EQ)
				{
					baseLexer.restore(currentPosition);

					baseLexer.advance(); // <
					baseLexer.advance(); // %
					baseLexer.advance(); // ! or =
					addToken(JSP_IN_JAVA);
					myEnabledJavaTokens = true;
					return;
				}
				else
				{
					baseLexer.restore(currentPosition);
				}
			}
			else if(token2 == JavaTokenType.PERCEQ)
			{
				baseLexer.advance();

				// simple <%
				if(baseLexer.getTokenType() == JavaTokenType.WHITE_SPACE)
				{
					baseLexer.restore(currentPosition);

					baseLexer.advance(); // <
					baseLexer.advance(); // %=
					addToken(JSP_IN_JAVA);
					myEnabledJavaTokens = true;
					return;
				}
				else
				{
					baseLexer.restore(currentPosition);
				}
			}
			else
			{
				baseLexer.restore(currentPosition);
			}
		}

		advanceAs(baseLexer, JSP_IN_JAVA);
	}
}

@@ -1736,32 +1736,61 @@
 TE_SPACE)%0A%09%09%09%09%7B%0A
+%09%09%09%09%09addToken(JSP_IN_JAVA);%0A%0A
 %09%09%09%09%09baseLexer.r
@@ -1881,35 +1881,8 @@
 / %25%0A
-%09%09%09%09%09addToken(JSP_IN_JAVA);
 %0A%09%09%09
@@ -2003,56 +2003,8 @@
 EXCL
- %7C%7C baseLexer.getTokenType() == JavaTokenType.EQ
 )%0A%09%09
@@ -2041,32 +2041,61 @@
 rentPosition);%0A%0A
+%09%09%09%09%09addToken(JSP_IN_JAVA);%0A%0A
 %09%09%09%09%09baseLexer.a
@@ -2174,41 +2174,9 @@
 // !
- or =%0A%09%09%09%09%09addToken(JSP_IN_JAVA);
+%0A
 %0A%09%09%09
@@ -2347,120 +2347,36 @@
 %09%09%09%09
-baseLexer.advance();%0A%0A%09%09%09%09// simple %3C%25%0A%09%09%09%09if(baseLexer.getTokenType() == JavaTokenType.WHITE_SPACE)%0A%09%09%09%09%7B
+addToken(JSP_IN_JAVA);%0A
 %0A%09%09%09%09
-%09
 base
@@ -2400,33 +2400,32 @@
 rentPosition);%0A%0A
-%09
 %09%09%09%09baseLexer.ad
@@ -2434,33 +2434,32 @@
 nce(); // %3C%0A%09%09%09%09
-%09
 baseLexer.advanc
@@ -2473,37 +2473,9 @@
  %25=%0A
-%09%09%09%09%09addToken(JSP_IN_JAVA);%0A%09
+%0A
 %09%09%09%09
@@ -2502,33 +2502,32 @@
 = true;%0A%09%09%09%09
-%09
 return;%0A
 %09%09%09%09%7D%0A%09%09%09%09el
@@ -2518,76 +2518,8 @@
 rn;%0A
-%09%09%09%09%7D%0A%09%09%09%09else%0A%09%09%09%09%7B%0A%09%09%09%09%09baseLexer.restore(currentPosition);%0A%09%09%09%09%7D%0A
 %09%09%09%7D

allow directive without space after <%=Test %>