package iitb.cfilt.cpost.vgi;

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

import java.io.File;
import java.util.*;

public class VerbGroup7 {

	private static VerbGroupIdentifierRuleReader vgr;

	private static UTFWriter ob;

	public VerbGroup7() {
		try {
			vgr = new VerbGroupIdentifierRuleReader();
			File outfile = new File(ConfigReader.get("VGI.VGMarkingFile"));
			if (outfile.exists()) {
				outfile.delete();
				outfile = new File(ConfigReader.get("VGI.VGMarkingFile"));
			}
			ob = new UTFWriter(outfile);
		} catch (Exception e) {
			System.out.println(e.toString());
			e.printStackTrace();
		}
	}

	//public Vector<MorphologicallyAnalyzedToken> identifyVerbGroups1(
	public int [] identifyVerbGroups1(
			Vector<MorphologicallyAnalyzedToken> matv) {
		// Vector<Integer> vgi = new Vector<Integer>();
		int[] vgi = new int[matv.size()];
		int currentVGstartedAt = 0;
		int VGnumber = 1;
		int isEnd = 0, isAbort = 0;
		int next = 0;
		// String last = new String();
		boolean ContinueVG = false;

		for (int i = 0; i < matv.size(); i = next) {
			boolean isLastWordOfSentence = (i == matv.size() - 1);
			vgi[i] = 0;
			if(!isLastWordOfSentence){
				next = i+1;
			}
			//System.out.println("Working for " + token);
			//for(next = i+1; )
			MorphologicallyAnalyzedToken mat = matv.get(i);			
			MorphologicallyAnalyzedToken matNext = matv.get(next);
			while(matNext.getAmbiguityScheme().equalsIgnoreCase("particle") && next != matv.size() - 1){
				next++;
				matNext = matv.get(next);
			}
			String token = mat.getToken();
			String tokenNext = matNext.getToken();
			// TODO : code for conjunct verbs 
			/*if(!ContinueVG){
				if(vgr.coVerbsHash.containsKey(token)){
					if(vgr.coVerbsHash.get(token).contains(tokenNext + "ना")){
						
					}
				}
			}*/
			VGproperties vgp = new VGproperties(mat,matNext);
			boolean isQualified = vgp.isQualified;			
			boolean isMustEndWord = vgp.isMustEndWord;			
			boolean hasMustEndSuffix = vgp.hasMustEndAuxSuffix || vgp.hasMustEndVMSuffix;
			boolean hasNotNullStemmerOutput = vgp.hasNotNullStemmerOutput;
			//System.out.println("Token : " + token + ", Next : " + tokenNext);
			if(!isQualified && isLastWordOfSentence){
				break;
			}
			if (hasNotNullStemmerOutput	&& mat.getStemmedOutputs().get(0).getCategory().trim().equals("SYM")) {				
				System.out.println("SYM");				
				continue;
			}			
			//boolean yes = false;
			if(vgr.coVerbsHash.containsKey(token) && !ContinueVG){
				boolean found = false;
				Vector<String> coVerbs = vgr.coVerbsHash.get(token);
				Vector<String> nextVerbRoots = new Vector<String>(vgp.nextVmRoots);
				nextVerbRoots.addAll(vgp.nextAuxRoots);
				for(int v=0; v<nextVerbRoots.size(); v++){
					if(coVerbs.contains(nextVerbRoots.get(v))){
						found = true;
						break;
					}
				}
				
				if(found){
					System.out.println("Found Co-Verb... " + token + ", " + tokenNext);
					vgi[i] = VGnumber;
					vgi[i+1] = VGnumber+1;
					if(next<matv.size()-1){
						next++;					
					}
					if(i < matv.size()-2 && matv.get(i+2).getAmbiguityScheme().contains("verb_aux")){
						VGnumber+=2;
						currentVGstartedAt = i+1;
						ContinueVG = true;
					}					
					continue;
				}				
			}
			if(vgr.possPRPs.contains(mat.getToken())){
				if(!isOnlyVerb(matNext)){
					next++;
				}
				continue;
			}						
			if ( hasNotNullStemmerOutput &&  isQualified  ) {
				// check if end word or end suffix //
				if(isLastWordOfSentence || hasMustEndSuffix || isMustEndWord){
					/* DONE : end here and break*/
					vgi[i] = VGnumber;
					VGnumber = 1;
					ContinueVG = false;
					if(isLastWordOfSentence){
						break;
					}
					continue;
				}
			
				// For main verb
				if(!ContinueVG && isVerb(mat)){
					currentVGstartedAt = i;
					//check for adverbial suffix-word pair//
					if(vgp.hasAdverbialAuxSuffixWord || vgp.hasAdverbialVMSuffixWord){					
							// End here.
							vgi[i] = VGnumber;
							vgi[next] = VGnumber+1;
							next++;
							VGnumber = 1;
							ContinueVG = false;
							continue;
						}
					//}
					if(!isVerbAux(matNext)){
						if(isVerb(matNext)){
							/* DONE : check reduplication */
							if(token.equals(tokenNext)){
								/* DONE : reduplication treatment */
								vgi[i] = VGnumber;
								vgi[next] = VGnumber+1;
								next++;
								VGnumber = 1;
								ContinueVG = false;
								continue;
							}
							/* TODO : check else case */
						}
						else{
							/* DONE : single word VG */
							if(isOnlyVerb(mat)){
								vgi[i] = VGnumber;
								VGnumber = 1;
								ContinueVG = false;
								continue;
							}
							/* TODO : check else case */
						}
					}
					else{  // Next is Aux
						/* TODO : Apply Main verb rules. */
						if(vgp.noVmSufixes){ // no suffix
							if(!vgr.tenseCases.contains(tokenNext)){
								/* start VG */
								//System.out.println("1. VG Started at " + i);
								currentVGstartedAt = i;
								vgi[i] = VGnumber;
								VGnumber++;
								ContinueVG = true;
								continue;
							}
							/* TODO : check else case */
							/* I guess nothing to do. */
						}
						else{ // It has suffix
							//String suffix = getVMSuffix(mat);							
							if(vgp.isNextAuxAllowedAfterThisVM){
								/* start VG */
								//System.out.println("2. VG Started at " + i);
								currentVGstartedAt = i;
								vgi[i] = VGnumber;
								VGnumber++;
								ContinueVG = true;
								continue;
							}
							/* TODO : check else case */
							else{
								if(vgp.hasAdverbialVMSuffix){
									vgi[i] = VGnumber;
									VGnumber = 1;
									ContinueVG = false;
									continue;
								}
								/* Abort here */
								next = currentVGstartedAt + 1; 
								VGnumber = 1;
								vgi[currentVGstartedAt] = 0;
								/*if(matv.get(currentVGstartedAt).getAmbiguityScheme().contains("noun")){
									vgi[currentVGstartedAt] = 100;
								}*/
								System.out.println("1. Going back to : " + next);
								ContinueVG = false;
								isAbort = 1;
							}
						}
					}
				}
				else if(ContinueVG && isVerbAux(mat)){
					/* TODO : Apply new aux rules */					
					HashMap<String, Vector<String>> nextRootHash = vgr.auxSuffixNextRootRuleHash.get(getAuxRoot(mat));
					HashMap<String, Vector<String>> nextTokenHash = vgr.auxSuffixNextTokenRuleHash.get(getAuxRoot(mat));
					String suffix = "";
					if(getAuxSuffix(mat).isEmpty()){
						suffix = "Null";
					}
					else{
						suffix = getAuxSuffix(mat);
					}
					if(isVerbAux(matNext)){ // Check if next word is qualified to VAUX.
						if(vgp.isNextAuxAllowedAfterThisAux){
							vgi[i] = VGnumber;
							VGnumber++;
							ContinueVG = true;
							continue;
						}
						else if(vgp.hasAdverbialAuxSuffix){
							vgi[i] = VGnumber;
							VGnumber = 1;
							ContinueVG = false;
							continue;
						}
						/* TODO : this is commented but need to think about it.
						/*else if (nextTokenHash != null && nextTokenHash.containsKey(suffix) && nextTokenHash.get(suffix).contains("Null")) {  // || nextRootHash.get(suffix).contains("Null")
							vgi[i] = VGnumber;	VGnumber = 1;	ContinueVG = false;	continue;	}*/						
						/* TODO : check else case */
						else{
							/* Abort here */
							next = currentVGstartedAt + 1; 
							VGnumber = 1;
							vgi[currentVGstartedAt] = 0;
							/*if(matv.get(currentVGstartedAt).getAmbiguityScheme().contains("noun")){
								vgi[currentVGstartedAt] = 100;
							}*/
							System.out.println("2. Going back to : " + next + "Aborted at " + token);							
							ContinueVG = false;
							isAbort = 1;
						}
					}
					else if (vgp.isCanEndToken) { 
						vgi[i] = VGnumber;
						VGnumber = 1;
						ContinueVG = false;
						continue;
					}
					/* TODO : check else case 
					 * Guess : should Abort in case of next word is an auxiliary*/
					/*else if(isVerbAux(matNext)) {	 Abort here	
					 * 	next = currentVGstartedAt + 1;	VGnumber = 1;	vgi[currentVGstartedAt] = 0; System.out.println("3. Going back to : " + next);
						ContinueVG = false;	isAbort = 1;	}*/
					else{
						vgi[i] = VGnumber;
						VGnumber = 1;
						ContinueVG = false;
						continue;
					}
				}
				/* TODO : check else case 
				 * I think : case will never apear*/
			}
			
		}
		
		//return matv;
		return vgi;
	}

	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*");
		/*for(int i=0; i< mat.getStemmedOutputs().size(); i++){
			if(isVerb(mat.getStemmedOutputs().get(i))){
				retval = true;
				break;
			}
		}*/
		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){
					retval.add(mat.getStemmedOutputs().get(i).getSuffixList().get(0));
					//break;
				}	
			}
		}
		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;
	}
	
	/*boolean applyRule(String rule, String param, String	replace){
		boolean retval = false;
		
		return retval;
	}
	
	public boolean isCoVerb(MorphologicallyAnalyzedToken mat, MorphologicallyAnalyzedToken matNext){
		boolean retVal = false;
		if(vgr.coVerbsHash.containsKey(mat.getToken())){
			
		}
		return retVal;
	}*/

	public static void main(String args[]) {
		ConfigReader.read(args[0]);
		Stemmer stemmer = new Stemmer();
		VerbGroup7 vb = new VerbGroup7();
		Vector<StemmedToken> stemmedTokens = new Vector<StemmedToken>();
		Vector<MorphologicallyAnalyzedToken> maTokens = new Vector<MorphologicallyAnalyzedToken>();
		String sentence = "गया दो ही खेल रहे थे";//ओवरों का कर दिया गया है";//राम कर चुका देगा";//अच्छा चल भी रहा था";//सुलझा लेना चाहिए था";//संतोष करना पड़";// पड़";//ले जाया जा सकता था";//कर दिया गया है";//संतोष करना पड़";//पड़ा";//पड़ा";//संपर्क बनाया हुआ है";//घायल हुए थे";//योजना बना रहे थे";//आत्मदाह कर लिया";//गिरफ़्तार किया गया है";//टीम का साथ दे सकेंगे";//निशाना बनाता आया है";//हमला करने की योजना बना रहे थे";//आत्मदाह कर लिया .";//गिरफ़्तार किया गया है";
		//निर्मला का यह पन्द्रहवां साल था";//पुलिस का होना था";//राम कर चुका देगा";//होगा";// राम खाना खाता है ";
		String tokens[] = sentence.split(" ");
		List l = Arrays.asList(tokens);
		Vector<String> tokenList = new Vector<String>(l);
		MorphologicalAnalyzerRuleReader MAR = new MorphologicalAnalyzerRuleReader();
		MorphologicalAnalyzer ma = new MorphologicalAnalyzer();
		stemmedTokens = stemmer.stem(tokenList);
		maTokens = ma.analyze(stemmedTokens);
		int vg[] = new int[stemmedTokens.size()];
		vg = vb.identifyVerbGroups1(maTokens);
		for (int i = 0; i < vg.length; i++) {
			System.out.print(maTokens.get(i).getToken() + "-" + vg[i] + "\t");
		}
		
		/*boolean is = vgr.mustEndWords.contains("");
		if(is){
			System.out.println("Working..");
		}
		else{
			System.out.println("Sorry..");
		}
		for(int i=0; i< vgr.mustEndWords.size(); i++){
			System.out.println(vgr.mustEndWords.get(i));
		}*/
	}
}

