package lexicon;
import java.io.*;
import java.sql.Timestamp;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import base.*;

public class LexRuleReader {
	private String suffixRuleForNNFilename = "";
	private String reAdjustmentRuleForNNFilename = "";
	private String rulesForAdjFilename = "";
	private String rulesForQuantifierIntensifierFileName = "";
	private String rulesForOrdinalsFileName = "";
	private String rulesForVerbsFileName = "";
	public HashMap<String, Vector<NNSuffixRule>> suffixRuleNNHash = new HashMap<String, Vector<NNSuffixRule>>();
	public HashMap<String, Vector<NNReadjustmentRule>> reAdjustmentRuleNNHash = new HashMap<String, Vector<NNReadjustmentRule>>();
	public HashMap<String, Vector<LexGeneralRule>> adjRuleHash = new HashMap<String, Vector<LexGeneralRule>>();
	public HashMap<String, Vector<LexGeneralRule>> QnfInfRuleHash = new HashMap<String, Vector<LexGeneralRule>>();
	public HashMap<String, Vector<LexGeneralRule>> OrdinalRuleHash = new HashMap<String, Vector<LexGeneralRule>>();
	public HashMap<String, HashMap<String, Vector<VerbRule>>> verbRuleHash = new HashMap<String, HashMap<String,Vector<VerbRule>>>();
	//public HashMap
	public Vector<String> suffixes = new Vector<String>();
	
	//private boolean populated = false;
	public LexRuleReader()
	{
			suffixRuleForNNFilename = ConfigReader.get("NewStemmer.NN_suffix_Rules");
			reAdjustmentRuleForNNFilename = ConfigReader.get("NewStemmer.NN_ReAdjustment_Rules");
			rulesForAdjFilename = ConfigReader.get("NewStemmer.Adj_Rules");
			rulesForQuantifierIntensifierFileName = ConfigReader.get("NewStemmer.Qnf_Inf_Rules");
			rulesForOrdinalsFileName = ConfigReader.get("NewStemmer.Ordinal_Rules");
			rulesForVerbsFileName = ConfigReader.get("NewStemmer.Verb_Rules");
			try
			{
				BufferedReader bsrr = new BufferedReader(new InputStreamReader(new FileInputStream(suffixRuleForNNFilename), "UTF8"));
				String line = "";
		
				while (line != null)
				{				
					line = bsrr.readLine();
					if(line != null)
					{
						line = line.trim();
						if(line.length()!=0 && !line.startsWith("//"))
						{
							String lineComponents[] = line.split("/");
							if(lineComponents.length == 3)
							{
								String suffix = lineComponents[0].trim();
								String constraint = lineComponents[1].trim();
								String morphAnalysis = lineComponents[2].trim();
								/*String morphs[] = morphAnalysis.split(",");
								if(morphs.length>2){
									
								}*/
								String stemFeatures[] = constraint.split(",");
								char clas = stemFeatures[0].trim().charAt(0);
								char gender = stemFeatures[1].trim().charAt(0); // Here in all rules Gender is mentioned as 'X'. Therefor no treatment is given. Otherwise It should be read as +/- and given M/F accordingly. 
								String ending = stemFeatures[2].trim();
								NNSuffixRule sr = new NNSuffixRule(suffix, clas,gender,ending,morphAnalysis);
								if(suffixRuleNNHash.containsKey(suffix)){
									Vector<NNSuffixRule> srv = suffixRuleNNHash.get(suffix);
									srv.add(sr);
									suffixRuleNNHash.put(suffix, srv);
								}
								else{
									Vector<NNSuffixRule> srv = new Vector<NNSuffixRule>();
									srv.add(sr);
									suffixRuleNNHash.put(suffix, srv);
								}
								
								if(!suffixes.contains(suffix)){
									suffixes.add(suffix);
								}
								
							}
						}
					}
				}
				
				bsrr.close();
				
				bsrr = new BufferedReader(new InputStreamReader(new FileInputStream(reAdjustmentRuleForNNFilename), "UTF8"));
				line = "";
				
				while (line != null)
				{
					line = bsrr.readLine();
					if(line != null)
					{
						line = line.trim();
						if(line.length()!=0 && !line.startsWith("//"))
						{
							String lineComponents[] = line.split("/");
							String suffixListToAdd[] = lineComponents[0].trim().split("or");							
							String suffixToDelete = lineComponents[1].trim();
							String featuresANDsuffix[] = lineComponents[2].trim().split(":");							
							String stemFeatureStrings[] = featuresANDsuffix[0].trim().split("or");
							/*char clas = stemFeatures[0].trim().charAt(0);
							char masculine = stemFeatures[1].trim().charAt(0);
							String askSmriti = stemFeatures[2].trim();*/
							String suffixesObserved[] = featuresANDsuffix[1].trim().split("or");
							Vector<StemFeatures> sfv = new Vector<StemFeatures>();
							for(int sfs=0; sfs<stemFeatureStrings.length; sfs++){
								String stemFeatures[] = stemFeatureStrings[sfs].trim().split(",");
								char clas = stemFeatures[0].trim().charAt(0);
								char gender = stemFeatures[1].trim().charAt(0);
								String askSmriti = stemFeatures[2].trim();
								StemFeatures sf = new StemFeatures(clas,gender,askSmriti);
								sfv.add(sf);
							}
							for(int so=0; so<suffixesObserved.length; so++){
								String suffixObserved = suffixesObserved[so].trim();
								if(reAdjustmentRuleNNHash.containsKey(suffixObserved)){
									Vector<NNReadjustmentRule> rrv = reAdjustmentRuleNNHash.get(suffixObserved);									
									for(int sfs=0; sfs<sfv.size(); sfs++){
										for(int sla=0; sla<suffixListToAdd.length; sla++){
											String suffixToAdd = suffixListToAdd[sla].trim();
											NNReadjustmentRule rr = new NNReadjustmentRule(suffixToAdd,suffixToDelete,sfv.get(sfs),suffixObserved);
											rrv.add(rr);
										}
									}
									reAdjustmentRuleNNHash.put(suffixObserved, rrv);
								}
								else{
									Vector<NNReadjustmentRule> rrv = new Vector<NNReadjustmentRule>();
									for(int sfs=0; sfs<sfv.size(); sfs++){
										for(int sla=0; sla<suffixListToAdd.length; sla++){
											String suffixToAdd = suffixListToAdd[sla].trim();
											NNReadjustmentRule rr = new NNReadjustmentRule(suffixToAdd,suffixToDelete,sfv.get(sfs),suffixObserved);
											rrv.add(rr);
										}
									}
									reAdjustmentRuleNNHash.put(suffixObserved, rrv);
								}
							}
		
						}
					}
					
				}
				
				bsrr.close();
				
				bsrr = new BufferedReader(new InputStreamReader(new FileInputStream(rulesForAdjFilename), "UTF8"));
				line = "";
				
				while (line != null)
				{
					line = bsrr.readLine();
					if(line != null)
					{
						line = line.trim();
						if(line.length()!=0 && !line.startsWith("//"))
						{
							String lineComponents[] = line.split("/");
							String suffixToAdd = lineComponents[0].trim();
							String suffixToDelete = lineComponents[1].trim();
							char clas = lineComponents[2].trim().charAt(0);
							String morphAnalysis = lineComponents[3].trim();
							String suffixObserved = lineComponents[4].trim();
							LexGeneralRule adjRule = new LexGeneralRule(suffixToAdd, suffixToDelete, clas, morphAnalysis, suffixObserved);
							if(adjRuleHash.containsKey(suffixToDelete)){
								Vector<LexGeneralRule> adjRules = adjRuleHash.get(suffixToDelete);
								adjRules.add(adjRule);
								adjRuleHash.put(suffixToDelete, adjRules);
							}
							else{
								Vector<LexGeneralRule> adjRules = new Vector<LexGeneralRule>();
								adjRules.add(adjRule);
								adjRuleHash.put(suffixToDelete, adjRules);
							}
							
							if(!suffixes.contains(suffixToDelete)){
								suffixes.add(suffixToDelete);
							}
						}						
					}					
				}
				
				bsrr.close();
				
				bsrr = new BufferedReader(new InputStreamReader(new FileInputStream(rulesForQuantifierIntensifierFileName), "UTF8"));
				line = "";
				
				while (line != null)
				{
					line = bsrr.readLine();
					if(line != null)
					{
						line = line.trim();
						if(line.length()!=0 && !line.startsWith("//"))
						{
							String lineComponents[] = line.split("/");
							String suffixToAdd = lineComponents[0].trim();
							String suffixToDelete = lineComponents[1].trim();
							char clas = lineComponents[2].trim().charAt(0);
							String morphAnalysis = lineComponents[3].trim();
							String suffixObserved = lineComponents[4].trim();
							LexGeneralRule qnfInfRule = new LexGeneralRule(suffixToAdd, suffixToDelete, clas, morphAnalysis, suffixObserved);
							if(QnfInfRuleHash.containsKey(suffixToDelete)){
								Vector<LexGeneralRule> qnfInfRules = QnfInfRuleHash.get(suffixToDelete);
								qnfInfRules.add(qnfInfRule);
								QnfInfRuleHash.put(suffixToDelete, qnfInfRules);
							}
							else{
								Vector<LexGeneralRule> qnfInfRules = new Vector<LexGeneralRule>();
								qnfInfRules.add(qnfInfRule);
								QnfInfRuleHash.put(suffixToDelete, qnfInfRules);
							}
							
							if(!suffixes.contains(suffixToDelete)){
								suffixes.add(suffixToDelete);
							}
						}						
					}					
				}
				
				bsrr.close();
				
				bsrr = new BufferedReader(new InputStreamReader(new FileInputStream(rulesForOrdinalsFileName), "UTF8"));
				line = "";
				
				while (line != null)
				{
					line = bsrr.readLine();
					if(line != null)
					{
						line = line.trim();
						if(line.length()!=0 && !line.startsWith("//"))
						{
							String lineComponents[] = line.split("/");							
							String suffixToDelete = lineComponents[1].trim();
							char clas = lineComponents[2].trim().charAt(0);
							String morphAnalysis = lineComponents[3].trim();
							String suffixObserved = lineComponents[4].trim();
							String[] suffixesToAdd = lineComponents[0].trim().split("or");
							for(int i=0; i<suffixesToAdd.length; i++){
								String suffixToAdd = suffixesToAdd[i].trim();
								LexGeneralRule ordinalRule = new LexGeneralRule(suffixToAdd, suffixToDelete, clas, morphAnalysis, suffixObserved);
								if(OrdinalRuleHash.containsKey(suffixToDelete)){
									Vector<LexGeneralRule> ordinalRules = OrdinalRuleHash.get(suffixToDelete);
									ordinalRules.add(ordinalRule);
									OrdinalRuleHash.put(suffixToDelete, ordinalRules);
								}
								else{
									Vector<LexGeneralRule> ordinalRules = new Vector<LexGeneralRule>();
									ordinalRules.add(ordinalRule);
									OrdinalRuleHash.put(suffixToDelete, ordinalRules);
								}
							}
							
							if(!suffixes.contains(suffixToDelete)){
								suffixes.add(suffixToDelete);
							}
						}						
					}					
				}
				bsrr.close();
				
				bsrr = new BufferedReader(new InputStreamReader(new FileInputStream(rulesForVerbsFileName), "UTF8"));
				line = "";
				
				String typeOfRule = ""; 
				while (line != null)
				{
					line = bsrr.readLine();
					if(line != null)
					{
						line = line.trim();
						if(line.length()!=0 && !line.startsWith("//"))
						{
							if(line.startsWith("Rules For")){
								String [] lineparts = line.split(" ");
								typeOfRule = lineparts[2].trim();
							}
							else{
								hashIt(typeOfRule,line);
							}
							
						}						
					}					
				}
				
			}catch(Exception e)
			{
				System.out.println(e.toString());
				e.printStackTrace();
			}
	}
	
	void hashIt(String typeOfRule, String line){
		if(typeOfRule.equalsIgnoreCase("Readjustment")){
			hashToReadjustment(line);
		}
		else{
			hashDefault(typeOfRule,line);
		}
	}
	
	void hashDefault(String typeOfRule, String line){
		String lineComponents[] = line.split("/");							
		String [] suffixeList = lineComponents[0].trim().split("or");		
		String [] morphs = lineComponents[1].trim().split("or");
		String [] constraints;
		if(lineComponents.length>2){
			constraints = lineComponents[2].trim().split("or");
		}
		else{
			constraints = new String[1];
			constraints[0] = "Null";
		}		
		for(int i=0; i<suffixeList.length; i++){
			String suffix = suffixeList[i].trim();
			VerbRule verbRule = new VerbRule(suffix, morphs, constraints);
			if(verbRuleHash.containsKey(typeOfRule)){
				HashMap<String, Vector<VerbRule>> typeHash = verbRuleHash.get(typeOfRule);
				if(typeHash.containsKey(suffix)){
					Vector<VerbRule> verbRules = typeHash.get(suffix);
					verbRules.add(verbRule);
					typeHash.put(suffix, verbRules);
				}
				else{
					Vector<VerbRule> verbRules = new Vector<VerbRule>();
					verbRules.add(verbRule);
					typeHash.put(suffix, verbRules);
				}
			}
			else{
				HashMap<String, Vector<VerbRule>> typeHash = new HashMap<String, Vector<VerbRule>>();
				Vector<VerbRule> verbRules = new Vector<VerbRule>();
				verbRules.add(verbRule);
				typeHash.put(suffix, verbRules);
				verbRuleHash.put(typeOfRule, typeHash);
			}
			if(!suffixes.contains(suffix)){
				suffixes.add(suffix);
			}
		}		
		
	}
	
	void hashToReadjustment(String line){
		 String[] lineComponents = line.split("=");
		 String rule = lineComponents[0].trim();
		 String[] ruleComponents = rule.split("/");
		 String suffixToAdd = ruleComponents[0].trim();
		 String[] suffixesToDelete = ruleComponents[1].trim().split("or");
	}
}
