package iitb.cfilt.cpost.vgi;
import java.util.Vector;
import java.io.File;
import java.util.*;

import iitb.cfilt.cpost.ConfigReader;
import iitb.cfilt.cpost.UTFWriter;
import iitb.cfilt.cpost.ma.*;
import iitb.cfilt.cpost.newstemmer.*;

public class VGproperties {
	MorphologicallyAnalyzedToken mat;
	MorphologicallyAnalyzedToken matNext;
	VerbGroupIdentifierRuleReader vgir;
	boolean noVmSufixes;	
	boolean noAuxSufixes;	
	boolean noNextVmSufixes;
	boolean noNextAuxSufixes;	
	boolean noVmRoots;	
	boolean noAuxRoots;	
	boolean noNextVmRoots;	
	boolean noNextAuxRoots;
	Vector<String> vmSuffixes;
	Vector<String> auxSuffixes;
	Vector<String> nextVmSuffixes;
	Vector<String> nextAuxSuffixes;
	Vector<String> vmRoots;
	Vector<String> auxRoots;
	Vector<String> nextVmRoots;
	Vector<String> nextAuxRoots;
	boolean hasAdverbialVMSuffix;
	boolean hasAdverbialAuxSuffix;
	boolean hasAdverbialVMSuffixWord;
	boolean hasAdverbialAuxSuffixWord;
	boolean hasMustEndVMSuffix;
	boolean hasMustEndAuxSuffix;
	boolean isQualified;
	boolean isMustEndWord;
	boolean hasNotNullStemmerOutput;
	boolean isNextAuxAllowedAfterThisVM;
	boolean isNextAuxAllowedAfterThisAux;
	boolean isCanEndToken;
	boolean isCoVerb;
	boolean isOnlyParticle;


	public VGproperties() {
		// TODO Auto-generated constructor stub
		mat = null;
		matNext = null;
		vgir = new VerbGroupIdentifierRuleReader();
		noVmSufixes = false;	
		noAuxSufixes = false;	
		noNextVmSufixes = false;
		noNextAuxSufixes = false;	
		noVmRoots = false;	
		noAuxRoots = false;	
		noNextVmRoots = false;	
		noNextAuxRoots = false;
		vmSuffixes = new Vector<String>();
		auxSuffixes = new Vector<String>();
		nextVmSuffixes = new Vector<String>();
		nextAuxSuffixes = new Vector<String>();
		vmRoots = new Vector<String>();
		auxRoots = new Vector<String>();
		nextVmRoots = new Vector<String>();
		nextAuxRoots = new Vector<String>();
		hasAdverbialVMSuffix = false;
		hasAdverbialAuxSuffix = false;
		hasAdverbialVMSuffixWord = false;
		hasAdverbialAuxSuffixWord = false;
		hasMustEndVMSuffix = false;
		hasMustEndAuxSuffix = false;
		isQualified = false;
		isMustEndWord = false;
		hasNotNullStemmerOutput = false;
		isNextAuxAllowedAfterThisVM = false;
		isNextAuxAllowedAfterThisAux = false;
		isCanEndToken = false;
		isCoVerb = false;
		isOnlyParticle = false;
	}
	VGproperties(MorphologicallyAnalyzedToken mat, MorphologicallyAnalyzedToken matNext){
		this.mat = mat;
		this.matNext = matNext;
		isOnlyParticle = isOnlyParticle(mat);//mat.getAmbiguityScheme().equalsIgnoreCase("particle");
		vgir = new VerbGroupIdentifierRuleReader();
		vmSuffixes = getVMSuffixes(this.mat);
		noVmSufixes = vmSuffixes.isEmpty();
		if(!noVmSufixes){
			noVmSufixes = true;
			for(int suf = 0; suf<vmSuffixes.size(); suf++ ){
				if(!vmSuffixes.get(suf).isEmpty()){
					noVmSufixes = false;
					break;
				}
				
			}
		}
		auxSuffixes = getAuxSuffixes(this.mat);
		noAuxSufixes = auxSuffixes.isEmpty();
		if(!noAuxSufixes){
			noAuxSufixes = true;
			for(int suf = 0; suf<auxSuffixes.size(); suf++ ){
				if(!auxSuffixes.get(suf).isEmpty()){
					noAuxSufixes = false;
					break;
				}
			}
		}
		nextVmSuffixes = getVMSuffixes(this.matNext);
		noNextVmSufixes = nextVmSuffixes.isEmpty();
		if(!noNextVmSufixes){
			noNextVmSufixes = true;
			for(int suf = 0; suf<nextVmSuffixes.size(); suf++ ){
				if(!nextVmSuffixes.get(suf).isEmpty()){
					noNextVmSufixes = false;
					break;
				}
			}
		}
		nextAuxSuffixes = getAuxSuffixes(this.matNext);
		noNextAuxSufixes = nextAuxSuffixes.isEmpty();
		noNextAuxSufixes = nextAuxSuffixes.isEmpty();
		if(!noNextAuxSufixes){
			noNextAuxSufixes = true;
			for(int suf = 0; suf<nextAuxSuffixes.size(); suf++ ){
				if(!nextAuxSuffixes.get(suf).isEmpty()){
					noNextAuxSufixes = false;
					break;
				}
			}
		}
		vmRoots = getVMRoots(this.mat);
		noVmRoots = vmRoots.isEmpty();
		auxRoots = getAuxRoots(this.mat);
		noAuxRoots = auxRoots.isEmpty();
		nextVmRoots = getVMRoots(this.matNext);
		noNextVmRoots = nextVmRoots.isEmpty();
		nextAuxRoots = getAuxRoots(this.matNext);
		noNextAuxRoots = nextAuxRoots.isEmpty();
		hasNotNullStemmerOutput = this.mat.getStemmedOutputs() != null && this.mat.getStemmedOutputs().size() > 0;
		hasAdverbialVMSuffix = false;
		for(int suf=0; suf<vmSuffixes.size(); suf++){
			if(vgir.adverbialSuffixes.contains(vmSuffixes.get(suf))){
				hasAdverbialVMSuffix = true;
				break;
			}
		}			
		hasAdverbialAuxSuffix = false;
		for(int suf=0; suf<auxSuffixes.size(); suf++){
			if(vgir.adverbialSuffixes.contains(auxSuffixes.get(suf))){
				hasAdverbialAuxSuffix = true;
				break;
			}
		}
		hasAdverbialVMSuffixWord = false;
		for(int suf=0; suf<vmSuffixes.size(); suf++){
			if(vgir.adverbialSuffix_Words.containsKey(vmSuffixes.get(suf))){
				if(vgir.adverbialSuffix_Words.get(vmSuffixes.get(suf)).contains(this.matNext.getToken())){
					hasAdverbialVMSuffixWord = true;
					break;
				}
			}
		}			
		hasAdverbialAuxSuffixWord = false;
		for(int suf=0; suf<auxSuffixes.size(); suf++){
			if(vgir.adverbialSuffix_Words.containsKey(auxSuffixes.get(suf))){
				if(vgir.adverbialSuffix_Words.get(auxSuffixes.get(suf)).contains(this.matNext.getToken())){
					hasAdverbialAuxSuffixWord = true;
					break;
				}
			}
		}
		hasMustEndVMSuffix = false;
		for(int suf=0; suf<vmSuffixes.size(); suf++){
			if(vgir.mustEndSuffixes.contains(vmSuffixes.get(suf))){
				hasAdverbialVMSuffix = true;
				break;
			}
		}			
		hasMustEndAuxSuffix = false;
		for(int suf=0; suf<auxSuffixes.size(); suf++){
			if(vgir.mustEndSuffixes.contains(auxSuffixes.get(suf))){
				hasAdverbialAuxSuffix = true;
				break;
			}
		}
		isQualified = isVerb(this.mat) || isVerbAux(this.mat);
		/*if(vgir==null){
			System.out.println("here it is");
		}
		System.out.println(this.mat.getToken());
		for(int itr = 0; itr<vgir.mustEndWords.size(); itr++){
			System.out.println(vgir.mustEndWords.get(itr));
		}*/
		if(vgir.mustEndWords!=null && !vgir.mustEndWords.isEmpty()){
			if( vgir.mustEndWords.contains(this.mat.getToken())){
				isMustEndWord = true;
			}
		}
		
		isNextAuxAllowedAfterThisVM = false;
		for(int suf=0; suf<vmSuffixes.size(); suf++){
			String suffix = vmSuffixes.get(suf);
			Set<String> suffixes = vgir.vmSuffixNextTokensHash.keySet();
			Iterator it = suffixes.iterator();
		    while (it.hasNext()) {		        
		        String suffixKey = (String) it.next();
		        //System.out.println("Here : " + suffixKey);
		        if(suffix.equals(suffixKey)){
		        	if(vgir.vmSuffixNextTokensHash.get(suffixKey).contains(this.matNext.getToken())){
						isNextAuxAllowedAfterThisVM = true;
						break;
					}
		        }
		    }
		    if(isNextAuxAllowedAfterThisVM){
		    	break;
		    }
			/*if(vgir.vmSuffixNextTokensHash.containsKey(suffix) &&  vgir.vmSuffixNextTokensHash.get(suffix).contains(this.matNext.getToken())){
				isNextAuxAllowedAfterThisVM = true;
				break;vgir.vmSuffixNextRootsHash.get(suffixKey).get(0).equals(root)
			}*/		    		    
			suffixes = vgir.vmSuffixNextRootsHash.keySet();
			it = suffixes.iterator();
		    while (it.hasNext()) {		        
		        String suffixKey = (String) it.next();		        
		        if(suffix.equals(suffixKey)){//(suffix.endsWith(suffixKey)){
		        	for(int rt = 0; rt<nextAuxRoots.size(); rt++){
						String root = nextAuxRoots.get(rt);
						//System.out.println(suffixKey + "\t" + root + "\t" + vgir.vmSuffixNextRootsHash.get(suffixKey).toString());
						if(vgir.vmSuffixNextRootsHash.get(suffixKey).contains(root.trim())){							
							isNextAuxAllowedAfterThisVM = true;
							break;
						}
					}
		        	if(isNextAuxAllowedAfterThisVM){
						break;
					}
		        }
		        if(isNextAuxAllowedAfterThisVM){
			    	break;
			    }
		    }		    
			/*for(int rt = 0; rt<nextAuxRoots.size(); rt++){
				String root = nextAuxRoots.get(rt);
				if(vgir.vmSuffixNextRootsHash.containsKey(suffix) && vgir.vmSuffixNextRootsHash.get(suffix).contains(root)){
					isNextAuxAllowedAfterThisVM = true;
					break;
				}
			}*/
		}
		
		isNextAuxAllowedAfterThisAux = false;
		for(int rt = 0; rt<auxRoots.size(); rt++){
			HashMap<String, Vector<String>> nextRootHash = vgir.auxSuffixNextRootRuleHash.get(auxRoots.get(rt));
			HashMap<String, Vector<String>> nextTokenHash = vgir.auxSuffixNextTokenRuleHash.get(auxRoots.get(rt));
			String suffix = "";
			if(auxSuffixes.get(rt).isEmpty()){
				suffix = "Null";
			}
			else{
				suffix = auxSuffixes.get(rt);
			}
			boolean is = false; 
			if(nextRootHash != null){
				for(int nrt = 0; nrt<nextAuxRoots.size(); nrt++){
					if(nextRootHash.containsKey(suffix) && nextRootHash.get(suffix).contains(nextAuxRoots.get(nrt))){
						is = true;
						break;
					}
				}
			}
			if(nextTokenHash != null){				
				if(nextTokenHash.containsKey(suffix) && nextTokenHash.get(suffix).contains(matNext.getToken())){
					is = true;
				}
			}
			if(is){
				isNextAuxAllowedAfterThisAux = true;
				break;
			}
		}	
		
		isCanEndToken = false;
		for(int rt = 0; rt<auxRoots.size(); rt++){
			HashMap<String, Vector<String>> nextRootHash = vgir.auxSuffixNextRootRuleHash.get(auxRoots.get(rt));
			HashMap<String, Vector<String>> nextTokenHash = vgir.auxSuffixNextTokenRuleHash.get(auxRoots.get(rt));
			String suffix = "";
			if(auxSuffixes.get(rt).isEmpty()){
				suffix = "Null";
			}
			else{
				suffix = auxSuffixes.get(rt);
			}
			if(nextTokenHash != null && nextTokenHash.containsKey(suffix) && nextTokenHash.get(suffix).contains("Null")){
				isCanEndToken = true;
				break;
			}
		}
		
		isCoVerb = false;
		if(vgir.coVerbsHash.containsKey(mat.getToken())){
			for(int rt=0; rt<nextVmRoots.size(); rt++){
				if(vgir.coVerbsHash.get(mat.getToken()).contains(nextVmRoots.get(rt) + "ना")){
					isCoVerb = true;
					break;
				}
			}
			if(!isCoVerb){
				for(int rt=0; rt<nextAuxRoots.size(); rt++){
					if(vgir.coVerbsHash.get(mat.getToken()).contains(nextAuxRoots.get(rt) + "ना")){
						isCoVerb = true;
						break;
					}
				}
			}
		}
	}
	
	boolean hasSuffix(StemmerRuleResult srr) {
		boolean retval = false;
		retval = srr.getSuffixList().size() > 0
				&& !(srr.getSuffixList().get(0).isEmpty());
		return retval;
	}

	boolean isVerb(StemmerRuleResult srr) {
		boolean retval = false;
		retval = srr.getCategory().equals("verb");
		return retval;
	}

	boolean isVerb(MorphologicallyAnalyzedToken mat) {
		boolean retval = false;
		retval = mat.getAmbiguityScheme().contains("*verb*") || mat.getAmbiguityScheme().contains("*verb") 
			|| mat.getAmbiguityScheme().contains("verb*") || mat.getAmbiguityScheme().equals("verb")
			|| mat.getAmbiguityScheme().startsWith("verb*");		
		return retval;
	}

	boolean isOnlyParticle(MorphologicallyAnalyzedToken mat) {
		boolean retval = false;
		retval = mat.getAmbiguityScheme().equals("particle");
		return retval;
	}
	
	boolean isVerbAux(MorphologicallyAnalyzedToken mat) {
		boolean retval = false;
		retval = mat.getAmbiguityScheme().contains("verb_aux");
		return retval;
	}

	boolean isVerbAux(StemmerRuleResult srr) {
		boolean retval = false;
		retval = srr.getCategory().equals("verb_aux");
		return retval;
	}
	
	boolean isOnlyVM(MorphologicallyAnalyzedToken mat) {
		boolean retval = false;
		retval = mat.getAmbiguityScheme().equals("verb");
		return retval;
	}

	boolean isOnlyVAux(MorphologicallyAnalyzedToken mat) {
		boolean retval = false;
		retval = mat.getAmbiguityScheme().equals("verb_aux");
		return retval;
	}
	
	boolean isOnlyVerb(MorphologicallyAnalyzedToken mat) {
		boolean retval = false;
		retval = isOnlyVM(mat) || isOnlyVAux(mat) || mat.getAmbiguityScheme().equals("verb*verb_aux") || mat.getAmbiguityScheme().equals("verb_aux*verb");
		return retval;
	}
	
	boolean agree(StemmerRuleResult srr, MorphologicallyAnalyzedToken mat) {
		boolean retval = false;
		for (int i = 0; i < mat.getStemmedOutputs().size(); i++) {
			if (mat.getStemmedOutputs().get(i).getSuffixList().contains(
					srr.getSuffixList().get(0))) {
				retval = true;
				break;
			}
		}
		return retval;
	}
	
	Vector<String> getAuxRoots(MorphologicallyAnalyzedToken mat){
		Vector <String> retval= new Vector<String>();
		for (int i = 0; i < mat.getStemmedOutputs().size(); i++) {
			if (mat.getStemmedOutputs().get(i).getCategory().equals("verb_aux")) {
				retval.add(mat.getStemmedOutputs().get(i).getRoot());
				//break;
			}
		}
		return retval;
	}
	
	Vector <String> getVMRoots(MorphologicallyAnalyzedToken mat){
		Vector <String> retval= new Vector<String>();
		for (int i = 0; i < mat.getStemmedOutputs().size(); i++) {
			if (mat.getStemmedOutputs().get(i).getCategory().equals("verb")) {
				retval.add(mat.getStemmedOutputs().get(i).getRoot());
				//break;
			}
		}
		return retval;
	}
	
	Vector <String> getAuxSuffixes(MorphologicallyAnalyzedToken mat){
		Vector <String> retval= new Vector<String>();
		for (int i = 0; i < mat.getStemmedOutputs().size(); i++) {
			if (mat.getStemmedOutputs().get(i).getCategory().equals("verb_aux")) {
				if(mat.getStemmedOutputs().get(i).getSuffixSize()>0){
					retval.add(mat.getStemmedOutputs().get(i).getSuffixList().get(0));
				}
				else{
					retval.add("");
				}				
			}
		}
		return retval;
	}
	
	Vector<String> getVMSuffixes(MorphologicallyAnalyzedToken mat){
		Vector <String> retval= new Vector<String>();
		for (int i = 0; i < mat.getStemmedOutputs().size(); i++) {
			if (mat.getStemmedOutputs().get(i).getCategory().equals("verb")) {
				if(mat.getStemmedOutputs().get(i).getSuffixSize()>0){
					//System.out.println("Adding: " + mat.getStemmedOutputs().get(i).getSuffixList().get(0));
					retval.add(mat.getStemmedOutputs().get(i).getSuffixList().get(0));
				}
				else{
					retval.add("");
				}
			}
		}
		return retval;
	}
	
	String getAuxRoot(MorphologicallyAnalyzedToken mat){
		String retval= "";
		for (int i = 0; i < mat.getStemmedOutputs().size(); i++) {
			if (mat.getStemmedOutputs().get(i).getCategory().equals("verb_aux")) {
				retval = mat.getStemmedOutputs().get(i).getRoot();
				break;
			}
		}
		return retval;
	}
	
	String getVMRoot(MorphologicallyAnalyzedToken mat){
		String retval= "";
		for (int i = 0; i < mat.getStemmedOutputs().size(); i++) {
			if (mat.getStemmedOutputs().get(i).getCategory().equals("verb")) {
				retval = mat.getStemmedOutputs().get(i).getRoot();
				break;
			}
		}
		return retval;
	}
	
	String getAuxSuffix(MorphologicallyAnalyzedToken mat){
		String retval= "";
		for (int i = 0; i < mat.getStemmedOutputs().size(); i++) {
			if (mat.getStemmedOutputs().get(i).getCategory().equals("verb_aux")) {
				if(mat.getStemmedOutputs().get(i).getSuffixSize()>0){
					retval = mat.getStemmedOutputs().get(i).getSuffixList().get(0);
					break;
				}
			}
		}
		return retval;
	}
	
	String getVMSuffix(MorphologicallyAnalyzedToken mat){
		String retval= "";
		for (int i = 0; i < mat.getStemmedOutputs().size(); i++) {
			if (mat.getStemmedOutputs().get(i).getCategory().equals("verb")) {
				if(mat.getStemmedOutputs().get(i).getSuffixSize()>0){
					retval = mat.getStemmedOutputs().get(i).getSuffixList().get(0);
					break;
				}	
			}
		}
		return retval;
	}
	
	

}
