/*
 * [The "BSD license"]
 *  Copyright (c) 2010 Terence Parr
 *  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.
 *  3. The name of the author may not be used to endorse or promote products
 *      derived from this software without specific prior written permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 THE AUTHOR 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.
 */
package org.antlr.analysis;

import org.antlr.codegen.CodeGenerator;
import org.antlr.grammar.v3.ANTLRParser;
import org.antlr.tool.Grammar;
import org.antlr.tool.GrammarAST;
import org.stringtemplate.v4.ST;
import org.stringtemplate.v4.STGroup;

import java.util.*;

/** A binary tree structure used to record the semantic context in which
 *  an NFA configuration is valid.  It's either a single predicate or
 *  a tree representing an operation tree such as: p1&amp;&amp;p2 or p1||p2.
 *
 *  For NFA o-p1-&gt;o-p2-&gt;o, create tree AND(p1,p2).
 *  For NFA (1)-p1-&gt;(2)
 *           |       ^
 *           |       |
 *          (3)-p2----
 *  we will have to combine p1 and p2 into DFA state as we will be
 *  adding NFA configurations for state 2 with two predicates p1,p2.
 *  So, set context for combined NFA config for state 2: OR(p1,p2).
 *
 *  I have scoped the AND, NOT, OR, and Predicate subclasses of
 *  SemanticContext within the scope of this outer class.
 *
 *  July 7, 2006: TJP altered OR to be set of operands. the Binary tree
 *  made it really hard to reduce complicated || sequences to their minimum.
 *  Got huge repeated || conditions.
 */
public abstract class SemanticContext {
	/** Create a default value for the semantic context shared among all
	 *  NFAConfigurations that do not have an actual semantic context.
	 *  This prevents lots of if!=null type checks all over; it represents
	 *  just an empty set of predicates.
	 */
	public static final SemanticContext EMPTY_SEMANTIC_CONTEXT = new Predicate(Predicate.INVALID_PRED_VALUE);

	/** Given a semantic context expression tree, return a tree with all
	 *  nongated predicates set to true and then reduced.  So p&amp;&amp;(q||r) would
	 *  return p&amp;&amp;r if q is nongated but p and r are gated.
	 */
	public abstract SemanticContext getGatedPredicateContext();

	/** Generate an expression that will evaluate the semantic context,
	 *  given a set of output templates.
	 */
	public abstract ST genExpr(CodeGenerator generator,
										   STGroup templates,
										   DFA dfa);

	public abstract boolean hasUserSemanticPredicate(); // user-specified sempred {}? or {}?=>
	public abstract boolean isSyntacticPredicate();

	/** Notify the indicated grammar of any syn preds used within this context */
	public void trackUseOfSyntacticPredicates(Grammar g) {
	}

	public static class Predicate extends SemanticContext {
		/** The AST node in tree created from the grammar holding the predicate */
		public GrammarAST predicateAST;

		/** Is this a {...}?=&gt; gating predicate or a normal disambiguating {..}?
		 *  If any predicate in expression is gated, then expression is considered
		 *  gated.
		 *
		 *  The simple Predicate object's predicate AST's type is used to set
		 *  gated to true if type==GATED_SEMPRED.
		 */
		protected boolean gated = false;

		/** syntactic predicates are converted to semantic predicates
		 *  but synpreds are generated slightly differently.
		 */
		protected boolean synpred = false;

		public static final int INVALID_PRED_VALUE = -2;
		public static final int FALSE_PRED = 0;
		public static final int TRUE_PRED = ~0;

		/** sometimes predicates are known to be true or false; we need
		 *  a way to represent this without resorting to a target language
		 *  value like true or TRUE.
		 */
		protected int constantValue = INVALID_PRED_VALUE;

		public Predicate(int constantValue) {
			predicateAST = new GrammarAST();
			this.constantValue=constantValue;
		}

		public Predicate(GrammarAST predicate) {
			this.predicateAST = predicate;
			this.gated =
				predicate.getType()==ANTLRParser.GATED_SEMPRED ||
				predicate.getType()==ANTLRParser.SYN_SEMPRED ;
			this.synpred =
				predicate.getType()==ANTLRParser.SYN_SEMPRED ||
				predicate.getType()==ANTLRParser.BACKTRACK_SEMPRED;
		}

		public Predicate(Predicate p) {
			this.predicateAST = p.predicateAST;
			this.gated = p.gated;
			this.synpred = p.synpred;
			this.constantValue = p.constantValue;
		}

		/** Two predicates are the same if they are literally the same
		 *  text rather than same node in the grammar's AST.
		 *  Or, if they have the same constant value, return equal.
		 *  As of July 2006 I'm not sure these are needed.
		 */
		@Override
		public boolean equals(Object o) {
			if ( !(o instanceof Predicate) ) {
				return false;
			}

			Predicate other = (Predicate)o;
			if (this.constantValue != other.constantValue){
				return false;
			}

			if (this.constantValue != INVALID_PRED_VALUE){
				return true;
			}

			return predicateAST.getText().equals(other.predicateAST.getText());
		}

		@Override
		public int hashCode() {
			if (constantValue != INVALID_PRED_VALUE){
				return constantValue;
			}

			if ( predicateAST ==null ) {
				return 0;
			}

			return predicateAST.getText().hashCode();
		}

		@Override
		public ST genExpr(CodeGenerator generator,
									  STGroup templates,
									  DFA dfa)
		{
			ST eST;
			if ( templates!=null ) {
				if ( synpred ) {
					eST = templates.getInstanceOf("evalSynPredicate");
				}
				else {
					eST = templates.getInstanceOf("evalPredicate");
					generator.grammar.decisionsWhoseDFAsUsesSemPreds.add(dfa);
				}
				String predEnclosingRuleName = predicateAST.enclosingRuleName;
				/*
				String decisionEnclosingRuleName =
					dfa.getNFADecisionStartState().getEnclosingRule();
				// if these rulenames are diff, then pred was hoisted out of rule
				// Currently I don't warn you about this as it could be annoying.
				// I do the translation anyway.
				*/
				//eST.add("pred", this.toString());
				if ( generator!=null ) {
					eST.add("pred",
									 generator.translateAction(predEnclosingRuleName,predicateAST));
				}
			}
			else {
				eST = new ST("<pred>");
				eST.add("pred", this.toString());
				return eST;
			}
			if ( generator!=null ) {
				String description =
					generator.target.getTargetStringLiteralFromString(this.toString());
				eST.add("description", description);
			}
			return eST;
		}

		@Override
		public SemanticContext getGatedPredicateContext() {
			if ( gated ) {
				return this;
			}
			return null;
		}

		@Override
		public boolean hasUserSemanticPredicate() { // user-specified sempred
			return predicateAST !=null &&
				   ( predicateAST.getType()==ANTLRParser.GATED_SEMPRED ||
					 predicateAST.getType()==ANTLRParser.SEMPRED );
		}

		@Override
		public boolean isSyntacticPredicate() {
			return predicateAST !=null &&
				( predicateAST.getType()==ANTLRParser.SYN_SEMPRED ||
				  predicateAST.getType()==ANTLRParser.BACKTRACK_SEMPRED );
		}

		@Override
		public void trackUseOfSyntacticPredicates(Grammar g) {
			if ( synpred ) {
				g.synPredNamesUsedInDFA.add(predicateAST.getText());
			}
		}

		@Override
		public String toString() {
			if ( predicateAST ==null ) {
				return "<nopred>";
			}
			return predicateAST.getText();
		}
	}

	public static class TruePredicate extends Predicate {
		public TruePredicate() {
			super(TRUE_PRED);
		}

		@Override
		public ST genExpr(CodeGenerator generator,
									  STGroup templates,
									  DFA dfa)
		{
			if ( templates!=null ) {
				return templates.getInstanceOf("true_value");
			}
			return new ST("true");
		}

		@Override
		public boolean hasUserSemanticPredicate() {
			return false; // not user specified.
		}

		@Override
		public String toString() {
			return "true"; // not used for code gen, just DOT and print outs
		}
	}

	public static class FalsePredicate extends Predicate {
		public FalsePredicate() {
			super(FALSE_PRED);
		}

		@Override
		public ST genExpr(CodeGenerator generator,
									  STGroup templates,
									  DFA dfa)
		{
			if ( templates!=null ) {
				return templates.getInstanceOf("false");
			}
			return new ST("false");
		}

		@Override
		public boolean hasUserSemanticPredicate() {
			return false; // not user specified.
		}

		@Override
		public String toString() {
			return "false"; // not used for code gen, just DOT and print outs
		}
	}

	public static abstract class CommutativePredicate extends SemanticContext {
		protected final Set<SemanticContext> operands = new HashSet<SemanticContext>();
		protected int hashcode;

		public CommutativePredicate(SemanticContext a, SemanticContext b) {
			if (a.getClass() == this.getClass()){
				CommutativePredicate predicate = (CommutativePredicate)a;
				operands.addAll(predicate.operands);
			} else {
				operands.add(a);
			}

			if (b.getClass() == this.getClass()){
				CommutativePredicate predicate = (CommutativePredicate)b;
				operands.addAll(predicate.operands);
			} else {
				operands.add(b);
			}

			hashcode = calculateHashCode();
		}

		public CommutativePredicate(HashSet<SemanticContext> contexts){
			for (SemanticContext context : contexts){
				if (context.getClass() == this.getClass()){
					CommutativePredicate predicate = (CommutativePredicate)context;
					operands.addAll(predicate.operands);
				} else {
					operands.add(context);
				}
			}

			hashcode = calculateHashCode();
		}

		@Override
		public SemanticContext getGatedPredicateContext() {
			SemanticContext result = null;
			for (SemanticContext semctx : operands) {
				SemanticContext gatedPred = semctx.getGatedPredicateContext();
				if ( gatedPred!=null ) {
					result = combinePredicates(result, gatedPred);
				}
			}
			return result;
		}

		@Override
		public boolean hasUserSemanticPredicate() {
			for (SemanticContext semctx : operands) {
				if ( semctx.hasUserSemanticPredicate() ) {
					return true;
				}
			}
			return false;
		}

		@Override
		public boolean isSyntacticPredicate() {
			for (SemanticContext semctx : operands) {
				if ( semctx.isSyntacticPredicate() ) {
					return true;
				}
			}
			return false;
		}

		@Override
		public void trackUseOfSyntacticPredicates(Grammar g) {
			for (SemanticContext semctx : operands) {
				semctx.trackUseOfSyntacticPredicates(g);
			}
		}

		@Override
		public boolean equals(Object obj) {
			if (this == obj)
				return true;

			if (obj.getClass() == this.getClass()) {
				CommutativePredicate commutative = (CommutativePredicate)obj;
				Set<SemanticContext> otherOperands = commutative.operands;
				if (operands.size() != otherOperands.size())
					return false;

				return operands.containsAll(otherOperands);
			}

			if (obj instanceof NOT)
			{
				NOT not = (NOT)obj;
				if (not.ctx instanceof CommutativePredicate && not.ctx.getClass() != this.getClass()) {
					Set<SemanticContext> otherOperands = ((CommutativePredicate)not.ctx).operands;
					if (operands.size() != otherOperands.size())
						return false;

					ArrayList<SemanticContext> temp = new ArrayList<SemanticContext>(operands.size());
					for (SemanticContext context : otherOperands) {
						temp.add(not(context));
					}

					return operands.containsAll(temp);
				}
			}

			return false;
		}

		@Override
		public int hashCode(){
			return hashcode;
		}

		@Override
		public String toString() {
			StringBuilder buf = new StringBuilder();
			buf.append("(");
			int i = 0;
			for (SemanticContext semctx : operands) {
				if ( i>0 ) {
					buf.append(getOperandString());
				}
				buf.append(semctx.toString());
				i++;
			}
			buf.append(")");
			return buf.toString();
		}

		public abstract String getOperandString();

		public abstract SemanticContext combinePredicates(SemanticContext left, SemanticContext right);

		public abstract int calculateHashCode();
	}

	public static class AND extends CommutativePredicate {
		public AND(SemanticContext a, SemanticContext b) {
			super(a,b);
		}

		public AND(HashSet<SemanticContext> contexts) {
			super(contexts);
		}

		@Override
		public ST genExpr(CodeGenerator generator,
									  STGroup templates,
									  DFA dfa)
		{
			ST result = null;
			for (SemanticContext operand : operands) {
				if (result == null) {
					result = operand.genExpr(generator, templates, dfa);
					continue;
				}

				ST eST;
				if ( templates!=null ) {
					eST = templates.getInstanceOf("andPredicates");
				}
				else {
					eST = new ST("(<left>&&<right>)");
				}
				eST.add("left", result);
				eST.add("right", operand.genExpr(generator,templates,dfa));
				result = eST;
			}

			return result;
		}

		@Override
		public String getOperandString() {
			return "&&";
		}

		@Override
		public SemanticContext combinePredicates(SemanticContext left, SemanticContext right) {
			return SemanticContext.and(left, right);
		}

		@Override
		public int calculateHashCode() {
			int hashcode = 0;
			for (SemanticContext context : operands) {
				hashcode = hashcode ^ context.hashCode();
			}

			return hashcode;
		}
	}

	public static class OR extends CommutativePredicate {
		public OR(SemanticContext a, SemanticContext b) {
			super(a,b);
		}

		public OR(HashSet<SemanticContext> contexts) {
			super(contexts);
		}

		@Override
		public ST genExpr(CodeGenerator generator,
									  STGroup templates,
									  DFA dfa)
		{
			ST eST;
			if ( templates!=null ) {
				eST = templates.getInstanceOf("orPredicates");
			}
			else {
				eST = new ST("(<operands; separator=\"||\">)");
			}
			for (SemanticContext semctx : operands) {
				eST.add("operands", semctx.genExpr(generator,templates,dfa));
			}
			return eST;
		}

		@Override
		public String getOperandString() {
			return "||";
		}

		@Override
		public SemanticContext combinePredicates(SemanticContext left, SemanticContext right) {
			return SemanticContext.or(left, right);
		}

		@Override
		public int calculateHashCode() {
			int hashcode = 0;
			for (SemanticContext context : operands) {
				hashcode = ~hashcode ^ context.hashCode();
			}

			return hashcode;
		}
	}

	public static class NOT extends SemanticContext {
		protected SemanticContext ctx;
		public NOT(SemanticContext ctx) {
			this.ctx = ctx;
		}

		@Override
		public ST genExpr(CodeGenerator generator,
									  STGroup templates,
									  DFA dfa)
		{
			ST eST;
			if ( templates!=null ) {
				eST = templates.getInstanceOf("notPredicate");
			}
			else {
				eST = new ST("!(<pred>)");
			}
			eST.add("pred", ctx.genExpr(generator,templates,dfa));
			return eST;
		}

		@Override
		public SemanticContext getGatedPredicateContext() {
			SemanticContext p = ctx.getGatedPredicateContext();
			if ( p==null ) {
				return null;
			}
			return new NOT(p);
		}

		@Override
		public boolean hasUserSemanticPredicate() {
			return ctx.hasUserSemanticPredicate();
		}

		@Override
		public boolean isSyntacticPredicate() {
			return ctx.isSyntacticPredicate();
		}

		@Override
		public void trackUseOfSyntacticPredicates(Grammar g) {
			ctx.trackUseOfSyntacticPredicates(g);
		}

		@Override
		public boolean equals(Object object) {
			if ( !(object instanceof NOT) ) {
				return false;
			}
			return this.ctx.equals(((NOT)object).ctx);
		}

		@Override
		public int hashCode() {
			return ~ctx.hashCode();
		}

		@Override
		public String toString() {
			return "!("+ctx+")";
		}
	}

	public static SemanticContext and(SemanticContext a, SemanticContext b) {
		//System.out.println("AND: "+a+"&&"+b);
		if (a instanceof FalsePredicate || b instanceof FalsePredicate)
			return new FalsePredicate();

		SemanticContext[] terms = factorOr(a, b);
		SemanticContext commonTerms = terms[0];
		a = terms[1];
		b = terms[2];

		boolean factored = commonTerms != null && commonTerms != EMPTY_SEMANTIC_CONTEXT && !(commonTerms instanceof TruePredicate);
		if (factored) {
			return or(commonTerms, and(a, b));
		}
		
		//System.Console.Out.WriteLine( "AND: " + a + "&&" + b );
		if (a instanceof FalsePredicate || b instanceof FalsePredicate)
			return new FalsePredicate();

		if ( a==EMPTY_SEMANTIC_CONTEXT || a==null ) {
			return b;
		}
		if ( b==EMPTY_SEMANTIC_CONTEXT || b==null ) {
			return a;
		}

		if (a instanceof TruePredicate)
			return b;

		if (b instanceof TruePredicate)
			return a;

		//// Factoring takes care of this case
		//if (a.Equals(b))
		//    return a;

		//System.out.println("## have to AND");
		AND result = new AND(a,b);
		if (result.operands.size() == 1) {
			return result.operands.iterator().next();
		}

		return result;
	}

	public static SemanticContext or(SemanticContext a, SemanticContext b) {
		//System.out.println("OR: "+a+"||"+b);
		if (a instanceof TruePredicate || b instanceof TruePredicate)
			return new TruePredicate();

		SemanticContext[] terms = factorAnd(a, b);
		SemanticContext commonTerms = terms[0];
		a = terms[1];
		b = terms[2];
		boolean factored = commonTerms != null && commonTerms != EMPTY_SEMANTIC_CONTEXT && !(commonTerms instanceof FalsePredicate);
		if (factored) {
			return and(commonTerms, or(a, b));
		}

		if ( a==EMPTY_SEMANTIC_CONTEXT || a==null || a instanceof FalsePredicate ) {
			return b;
		}

		if ( b==EMPTY_SEMANTIC_CONTEXT || b==null || b instanceof FalsePredicate ) {
			return a;
		}

		if ( a instanceof TruePredicate || b instanceof TruePredicate || commonTerms instanceof TruePredicate ) {
			return new TruePredicate();
		}

		//// Factoring takes care of this case
		//if (a.equals(b))
		//    return a;

		if ( a instanceof NOT ) {
			NOT n = (NOT)a;
			// check for !p||p
			if ( n.ctx.equals(b) ) {
				return new TruePredicate();
			}
		}
		else if ( b instanceof NOT ) {
			NOT n = (NOT)b;
			// check for p||!p
			if ( n.ctx.equals(a) ) {
				return new TruePredicate();
			}
		}

		//System.out.println("## have to OR");
		OR result = new OR(a,b);
		if (result.operands.size() == 1)
			return result.operands.iterator().next();

		return result;
	}

	public static SemanticContext not(SemanticContext a) {
		if (a instanceof NOT) {
			return ((NOT)a).ctx;
		}

		if (a instanceof TruePredicate)
			return new FalsePredicate();
		else if (a instanceof FalsePredicate)
			return new TruePredicate();

		return new NOT(a);
	}

	// Factor so (a && b) == (result && a && b)
	public static SemanticContext[] factorAnd(SemanticContext a, SemanticContext b)
	{
		if (a == EMPTY_SEMANTIC_CONTEXT || a == null || a instanceof FalsePredicate)
			return new SemanticContext[] { EMPTY_SEMANTIC_CONTEXT, a, b };
		if (b == EMPTY_SEMANTIC_CONTEXT || b == null || b instanceof FalsePredicate)
			return new SemanticContext[] { EMPTY_SEMANTIC_CONTEXT, a, b };

		if (a instanceof TruePredicate || b instanceof TruePredicate)
		{
			return new SemanticContext[] { new TruePredicate(), EMPTY_SEMANTIC_CONTEXT, EMPTY_SEMANTIC_CONTEXT };
		}

		HashSet<SemanticContext> opsA = new HashSet<SemanticContext>(getAndOperands(a));
		HashSet<SemanticContext> opsB = new HashSet<SemanticContext>(getAndOperands(b));

		HashSet<SemanticContext> result = new HashSet<SemanticContext>(opsA);
		result.retainAll(opsB);
		if (result.isEmpty())
			return new SemanticContext[] { EMPTY_SEMANTIC_CONTEXT, a, b };

		opsA.removeAll(result);
		if (opsA.isEmpty())
			a = new TruePredicate();
		else if (opsA.size() == 1)
			a = opsA.iterator().next();
		else
			a = new AND(opsA);

		opsB.removeAll(result);
		if (opsB.isEmpty())
			b = new TruePredicate();
		else if (opsB.size() == 1)
			b = opsB.iterator().next();
		else
			b = new AND(opsB);

		if (result.size() == 1)
			return new SemanticContext[] { result.iterator().next(), a, b };

		return new SemanticContext[] { new AND(result), a, b };
	}

	// Factor so (a || b) == (result || a || b)
	public static SemanticContext[] factorOr(SemanticContext a, SemanticContext b)
	{
		HashSet<SemanticContext> opsA = new HashSet<SemanticContext>(getOrOperands(a));
		HashSet<SemanticContext> opsB = new HashSet<SemanticContext>(getOrOperands(b));

		HashSet<SemanticContext> result = new HashSet<SemanticContext>(opsA);
		result.retainAll(opsB);
		if (result.isEmpty())
			return new SemanticContext[] { EMPTY_SEMANTIC_CONTEXT, a, b };

		opsA.removeAll(result);
		if (opsA.isEmpty())
			a = new FalsePredicate();
		else if (opsA.size() == 1)
			a = opsA.iterator().next();
		else
			a = new OR(opsA);

		opsB.removeAll(result);
		if (opsB.isEmpty())
			b = new FalsePredicate();
		else if (opsB.size() == 1)
			b = opsB.iterator().next();
		else
			b = new OR(opsB);

		if (result.size() == 1)
			return new SemanticContext[] { result.iterator().next(), a, b };

		return new SemanticContext[] { new OR(result), a, b };
	}

	public static Collection<SemanticContext> getAndOperands(SemanticContext context)
	{
		if (context instanceof AND)
			return ((AND)context).operands;

		if (context instanceof NOT) {
			Collection<SemanticContext> operands = getOrOperands(((NOT)context).ctx);
			List<SemanticContext> result = new ArrayList<SemanticContext>(operands.size());
			for (SemanticContext operand : operands) {
				result.add(not(operand));
			}
			return result;
		}

		ArrayList<SemanticContext> result = new ArrayList<SemanticContext>();
		result.add(context);
		return result;
	}

	public static Collection<SemanticContext> getOrOperands(SemanticContext context)
	{
		if (context instanceof OR)
			return ((OR)context).operands;

		if (context instanceof NOT) {
			Collection<SemanticContext> operands = getAndOperands(((NOT)context).ctx);
			List<SemanticContext> result = new ArrayList<SemanticContext>(operands.size());
			for (SemanticContext operand : operands) {
				result.add(not(operand));
			}
			return result;
		}

		ArrayList<SemanticContext> result = new ArrayList<SemanticContext>();
		result.add(context);
		return result;
	}
}
