package iitb.cfilt.cpost.lexicon;
import java.io.*;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import iitb.cfilt.cpost.*;
import iitb.cfilt.cpost.utils.*;

public class Wordlist{
	private static HashMap<String, HashMap<String,Vector<String>>> wordHash;
	private static HashMap<String, Vector<WordProperties>> wordToPropertiesMap;
	private static HashMap<String,String> parCat;
	private static HashMap<String,HashMap<String,HashSet<String>>> wordParadigmHash;
	private static String lexName = "";
//	private static FileReader lexicon;
	private static boolean populated = false;
	
	public static HashMap<String,HashMap<String,HashSet<String>>> firstcharCatParHash;
	
	public static Vector<String> temp = new Vector<String>();

	private Wordlist(){
//		lexName = ConfigReader.get("Lexicon.lexName");
//		wordHash = new HashMap<String, HashMap<String,Vector<String>>>();
//		parCat= new HashMap<String,String>();
//		generateWordlist(lexName);
	}

	public static void populate(){
		if(!lexName.equals(ConfigReader.get("Lexicon.newLexName"))){
			populated = false;
		}
		if(!populated){
			//System.out.println("WordList");
			lexName = ConfigReader.get("Lexicon.newLexName");
			//System.out.println(lexName);
			wordHash = new HashMap<String, HashMap<String,Vector<String>>>();
			wordToPropertiesMap = new HashMap<String, Vector<WordProperties>>();
			parCat= new HashMap<String,String>();
			wordParadigmHash = new HashMap<String,HashMap<String,HashSet<String>>>();
			firstcharCatParHash = new HashMap<String, HashMap<String,HashSet<String>>>();
			generateWordlist(lexName);
			populated = true;
		}
	}
	
	public static void populate(String baseDir){
		if(!lexName.equals(baseDir + ConfigReader.get("Lexicon.lexName"))){
			populated = false;
		}
		if(!populated){
			//System.out.println("WordList");
			lexName = baseDir + ConfigReader.get("Lexicon.lexName");
			//System.out.println(lexName);
			wordHash = new HashMap<String, HashMap<String,Vector<String>>>();
			wordToPropertiesMap = new HashMap<String, Vector<WordProperties>>();
			parCat= new HashMap<String,String>();
			wordParadigmHash = new HashMap<String,HashMap<String,HashSet<String>>>();
			firstcharCatParHash = new HashMap<String, HashMap<String,HashSet<String>>>();
			generateWordlist(lexName);
			populated = true;
		}
	}
	

	public static void populateFromFile(String strLexFile)
	{
			
			wordHash = new HashMap<String, HashMap<String,Vector<String>>>();
			wordToPropertiesMap = new HashMap<String, Vector<WordProperties>>();
			parCat= new HashMap<String,String>();
			generateWordlist(strLexFile);
			populated = true;
	}
	
	/**
	 *  Constructor for userdefined Lexicon file.
	 */
	/*
	public Wordlist(String lexName) {
		wordHash = new HashMap<String, HashMap<String,Vector<String>>>();
		parCat=new HashMap<String, String>();
		generateWordlist(lexName);
	}
	 */
	private static void generateWordlist(String lexiconFilename) {
		//System.out.println("Wordlist reading begins : " + new Timestamp(System.currentTimeMillis()));
		try {
			String line;
			BufferedReader bRead = new BufferedReader(new InputStreamReader(new FileInputStream(lexiconFilename), "UTF8"));
			line = " ";

			while (line != null){
				line = bRead.readLine();
				if(line != null){
					line = line.trim();
					if(line.length()!=0 && !line.startsWith("//"))
						hashIt(line);
				}
			}
			bRead.close();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		//System.out.println("Wordlist reading ends : " + new Timestamp(System.currentTimeMillis()));
	}

	public static String getCategory(String paradigm){
		return parCat.get(paradigm);
	}
	
	public static void hashLine(String line)
	{
		hashIt(line);
	}

	private static void hashIt(String line){

		Pattern pEnd = Pattern.compile(">");
		Matcher mEnd = pEnd.matcher(line);
		line = mEnd.replaceAll("");

		Pattern pStart = Pattern.compile("<");
		Matcher mStart = pStart.matcher(line);
		line = mStart.replaceAll("");

		Pattern pSplit = Pattern.compile(",");
		String[] lineComponents = pSplit.split(line);

		//UTFConsole.out.println("line is "+ line);
		String word = lineComponents[0].trim();
		String paradigm = lineComponents[1].trim();
		String category = lineComponents[2].trim();
		
		
		
		String firstchar = word.substring(0,1);
		
		if(firstcharCatParHash.containsKey(firstchar))
		{
			HashMap<String,HashSet<String>> catParHash = firstcharCatParHash.get(firstchar);
			if(catParHash.containsKey(category))
			{
				HashSet<String> parSet = catParHash.get(category);
				if(!parSet.contains(paradigm))
				{
					parSet.add(paradigm);
					catParHash.put(category,parSet);
				}
			}
			else
			{
				HashSet<String> parSet = new HashSet<String>();
				parSet.add(paradigm);
				catParHash.put(category,parSet);
			}
		}
		else
		{
			HashMap<String,HashSet<String>> catParHash = new HashMap<String,HashSet<String>>();
			HashSet<String> parSet = new HashSet<String>();
			parSet.add(paradigm);
			catParHash.put(category,parSet);
			firstcharCatParHash.put(firstchar,catParHash);
		}
		
		temp.add(word);
		
		String hashChar = null;
		if(word.length() >= 2)
			hashChar = word.substring(0,2);
		else
			hashChar = word.substring(0,1);
		
		if(wordParadigmHash.containsKey(hashChar))
		{
			HashMap<String,HashSet<String>> wordPar = wordParadigmHash.get(hashChar);
			if(wordPar.containsKey(word))
			{
				HashSet<String> parSet = wordPar.get(word);
				parSet.add(paradigm);
				wordPar.put(word,parSet);
			}
			else
			{
				HashSet<String> parSet = new HashSet<String>();
				parSet.add(paradigm);
				wordPar.put(word,parSet);
			}
		}
		else
		{
			HashMap<String,HashSet<String>> wordPar = new HashMap<String, HashSet<String>>();
			HashSet<String> parSet = new HashSet<String>();
			parSet.add(paradigm);
			wordPar.put(word,parSet);
			wordParadigmHash.put(hashChar,wordPar);
		}
		

		parCat.put(paradigm,category);
		
		String first_char;
		//if(word.length() < 2)
			first_char = word.substring(0,1);
		//else
		//	first_char = word.substring(0,2);
		
		
		//get index character
		//System.out.println("first_char is "+ first_char);
		if (wordHash.containsKey(first_char)) {

			HashMap<String,Vector<String>> par_word = (HashMap<String,Vector<String>>) wordHash.get(first_char);

			if (par_word.containsKey(paradigm)) {

				Vector<String> words = par_word.get(paradigm);
				words.add(word.trim());
				par_word.put(paradigm, words);
				wordHash.put(first_char, par_word);

			} else {

				Vector<String> words = new Vector<String>();
				words.add(word.trim());
				par_word.put(paradigm, words);
				wordHash.put(first_char, par_word);

			}

		} else {

			Vector<String> words = new Vector<String>();
			HashMap<String,Vector<String>> par_word = new HashMap<String,Vector<String>>();

			words.add(word.trim());
			par_word.put(paradigm, words);
			wordHash.put(first_char, par_word);
		}
		
		if(wordToPropertiesMap.containsKey(word)){
			Vector<WordProperties> props = wordToPropertiesMap.get(word);
			WordProperties newProperties = new WordProperties(paradigm, category);
			if(!props.contains(newProperties)){
				props.add(newProperties);
			}
		}
		else{
			Vector<WordProperties> props = new Vector<WordProperties>();
			props.add(new WordProperties(paradigm, category));
			wordToPropertiesMap.put(word, props);
		}
	}
	
	public static WordProperties lookup(String s, String par)
	{
		WordProperties retVal = null;
		//s = s.trim();
		//par = par.trim();
		String hashChar = null;
		if(s.length() >= 2)
			hashChar = s.substring(0,2);
		else if(s.length() == 1)
			hashChar = s.substring(0,1);
		else
			return(null);
		
		if(wordParadigmHash.containsKey(hashChar))
		{
			HashMap<String,HashSet<String>> wordPar = wordParadigmHash.get(hashChar);
			if(wordPar.containsKey(s))
			{
				if(wordPar.get(s).contains(par))
				{
					retVal = new WordProperties(par, (String) parCat.get(par));
				}
				else
					return(null);
			}
			else
				return(null);
		}
		else
			return(null);
		
		return(retVal);
	}

	public static WordProperties searchWordlistFor(String s, String par){
		
		WordProperties retVal = null;
		s = s.trim();
		par = par.trim();
		if (!(s.equals(null) || s.equals(""))){ 
			String first_char;
			//if(s.length() < 2)
				first_char = s.substring(0,1);
			//else
			//	first_char = s.substring(0,2);
			
			
			
			//String first_char= s.substring(0,1);
			if (wordHash.containsKey(first_char)){
				HashMap<String,Vector<String>> par_word = wordHash.get(first_char);

				Vector<String> words = par_word.get(par);
				if(words != null && words.contains(s)){
					retVal = new WordProperties(par, (String) parCat.get(par));
				}/*
				else{
					words = par_word.get("nst");
					if(words != null && words.contains(s)){
						//retVal = new WordProperties("nst", "nst");
					}
					else{
						boolean stemmerHack = true;
						if(stemmerHack){
//							words = par_word.get("wh");
//							if(words != null && words.contains(s)){
//							retVal = new WordProperties("wh", "wh");
//							}
//							else{
//							words = par_word.get("direct_pn");
//							if(words != null && words.contains(s)){
//							retVal = new WordProperties("direct_pn", "pn");
//							}
//							else{
//							words = par_word.get("oblique_pn");
//							if(words != null && words.contains(s)){
//							retVal = new WordProperties("oblique_pn", "pn");
//							}
//							else{
							words = par_word.get("proper_noun");
							if(words != null && words.contains(s)){
								retVal = new WordProperties("proper_noun", "pnoun");
							}
							else{
								words = par_word.get("ex_noun");
								if(words != null && words.contains(s)){
									retVal = new WordProperties("ex_noun", "noun");
								}
							}
//							}
//							}
//							}
						}
					}
				}*/
			}
		}
		return retVal;
	}


	public static Vector<WordProperties> searchWordlistFor(String s) {
		Vector<WordProperties> retVal = null;
		s = s.trim();
//		System.out.println("Searching for '" + s + "'");
		if(!s.equals(null) && !s.equals("")){
			String firstChar = s.substring(0, 1);
			if(wordHash.containsKey(firstChar)){
				retVal = new Vector<WordProperties>();
				HashMap<String,Vector<String>> par_word = wordHash.get(firstChar);
				Set<String> paradigms = par_word.keySet();
//				System.out.println("paradigms.contains(\"verb\") : " + paradigms.contains("verb"));
//				System.out.println("((Vector)par_word.get(\"verb\")).contains("+s+")" + ((Vector)par_word.get("verb")).contains(s));
				Iterator paradigmIter = paradigms.iterator();
				while(paradigmIter.hasNext()){
					String par = (String) paradigmIter.next();
//					if(par.equals("cardinal")){
//					System.out.println(par_word.get(par));
//					}
					Vector<String> temp = par_word.get(par);
					if(par_word.get(par).contains(s)){
						WordProperties wp = new WordProperties(par, (String)parCat.get(par));
						retVal.add(wp);
					}
				}
			}
		}
		return retVal;
	}
	
	public static Set<String> getAmbiguitySchemes(){
		HashSet<String> retVal = new HashSet<String>();
		Set<String> words = wordToPropertiesMap.keySet();
		HashSet<String> currentCategories = new HashSet<String>();
		for(String word : words){
			Vector<WordProperties> props = wordToPropertiesMap.get(word);
			for(WordProperties property : props){
				currentCategories.add(property.getCategory());
			}
			Vector<String> currentCategoriesVector = new Vector<String>(currentCategories);
			Collections.sort(currentCategoriesVector);
			String currentCategoryString = "";
			for(String category : currentCategoriesVector){
				currentCategoryString += category+"*";
			}
			retVal.add(currentCategoryString.substring(0, currentCategoryString.length()-1));
		}
		return retVal;
	}
	
	public static void main(String args[])
	{
		ConfigReader.read(args[0]);
		populate();
		Iterator<String> charIter = firstcharCatParHash.keySet().iterator();
		while(charIter.hasNext())
		{
			String firstchar = charIter.next();
			UTFConsole.out.println(firstchar);
			HashMap<String,HashSet<String>> catParHash = firstcharCatParHash.get(firstchar);
			
			Iterator<String> catIter = catParHash.keySet().iterator();
			while(catIter.hasNext())
			{
				String category = catIter.next();
				HashSet<String> parSet = catParHash.get(category);
				UTFConsole.out.println(category + ":" +parSet);
			}
			
		}
		UTFConsole.out.println(firstcharCatParHash);
		//long start,end;
		//System.out.println(new Timestamp(System.currentTimeMillis()).toString());
		//start = System.currentTimeMillis();
		//WordProperties wp = lookup("म्हण","verb");
		//WordProperties wp = lookup("म्ह","verb");
		
		//for(int i=0;i<10000;i++)
		//{
		//	WordProperties wp = searchWordlistFor(temp.get(i),"verb");
		//}
		//end = System.currentTimeMillis();
		//wp = searchWordlistFor("म्ह","verb");
		//System.out.println(new Timestamp(System.currentTimeMillis()).toString());
		//System.out.println("Start =" + new Timestamp(start));
		//System.out.println("End =" + new Timestamp(end));
		
	}
	
}

