//Class with some static WordNet helper functions
//Daniel Shiffman
//Programming from A to Z, Spring 2007
//http://www.shiffman.net/a2z
package genbook;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Set;

import net.didion.jwnl.*;
import net.didion.jwnl.data.*;
import net.didion.jwnl.data.Word;
import net.didion.jwnl.data.list.*;
import net.didion.jwnl.data.relationship.*;
import net.didion.jwnl.dictionary.*;

public class WordsHelper {

	// Dictionary object
	public static Dictionary wordnet;

	// Initialize the database!
	public static void initialize(String propsFile) {
		//String propsFile = "file_properties.xml";
		try {
			JWNL.initialize(new FileInputStream(propsFile));
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (JWNLException e) {
			e.printStackTrace();
		}
		// Create dictionary object
		wordnet = Dictionary.getInstance();
	}

	public static String getRandomSyn(String word) throws JWNLException{
		Synset aSynset = getRandomSynset(word);

		String resultWord = getRandomWordfromSynset(aSynset, word);

		return resultWord;
	}
	public static Synset getRandomSynset(String word) throws JWNLException {

		ArrayList senses = new ArrayList();
		senses = getAllSenses(word);

		// Pick a random Synset
		int rand = (int) (Math.random() * senses.size());

		//pick only one sense and return it
		Synset syn = (Synset) senses.get(rand);

		//System.out.println("random number is "+rand +" "+ senses.size() +" ``````````` "+ syn);

		return syn;

	}
	public static String getRandomWordfromSynset(Synset syn_, String word_) throws JWNLException{
		Synset syn = syn_;
		
		

		//insert only unique words into a hashmap
		HashMap words = new HashMap();

		Word[] tokens = syn.getWords();
		/*
		 *check if incoming token is the same as the root word word_. if it is then replace it with a new unique word
		 *The unique word is from a target synset of the source synset "syn".
		 *this also makes sure that the hash map is never empty 
		 */
		if(tokens.length==1 && tokens[0].getLemma().equalsIgnoreCase(word_)){
			String targetWord = getTargetWords(syn);
			words.put(targetWord,targetWord);
		}
		
		//System.out.println("lengthofWORD " + tokens.length);

		for (int i = 0; i < tokens.length; i++) {	
			String word = tokens[i].getLemma().toLowerCase();
			//System.out.println("word is "+word);
			if (!words.containsKey(word)){
				words.put(word,word);
			}
		}

		//remove the source word word_ from the hashmap to avoid having the same
		words.remove(word_);
		//to avoid hashmap containing null reenter the word word_ back into it..since some synsets 
		//might only contain the source word
		if(words.isEmpty()){
			System.out.println("** Spitting back the source word- since the synset only contains "+word_);

			words.put(word_,word_);
		}

		Iterator iterator = words.values().iterator();

		String word = null;
		int counter =0;
		int randomWord = (int) (Math.random() * words.size());

		while (iterator.hasNext()) {
			word = iterator.next().toString();
			word = word.replaceAll("_", " ");
			//System.out.println(randomWord+" <random>"+word);
			if (counter == randomWord){
				//System.out.println("FILTERed WORD "+word);
				return word;
			}
			counter=counter+1;
		}
		return null;
	}


//	get senses for all the passed words for all possible POS
	public static ArrayList getAllSenses(String word) throws JWNLException {

		ArrayList wordContainer = new ArrayList();

		//Indexwordset returns all the POS (as a noun,verb,adj and adverb) that this word could have.
		//the word "run" would return "run" as noun, running as adj and run as verb


		IndexWordSet set = Dictionary.getInstance().lookupAllIndexWords(word);
		if (set.size()==0){
			//try and catch the exception when the word does not exist or is wrong instead of printing a warning
			//temp sol below. change it
			System.out.println("Please check the word! Either you mispelled or there is no entry for realtionships in wordnet. The word was "+word);
		}

		//System.out.println("SET "+set.getValidPOSSet());

		/*
		int numberOfPOS = set.size();
		//System.out.println("SIZZE"+numberOfPOS);
		 */

		//get all the possible POS index words
		IndexWord[] indexWords = set.getIndexWordArray();


		for (int j = 0; j < indexWords.length; j++) {

			//System.out.println("POS(as LABEL) for the word <<< "+indexWords[j].getLemma()+ " >>> is "+indexWords[j].getPOS().getLabel());

			//String some = indexWords[j].getPOS().getLabel();
			//System.out.println("LABEL "+some);

			//add all the returned senses for all the POS of the source word to an arraylist
			wordContainer.addAll(getSenses(indexWords[j]));
		}

		return wordContainer;

	}

	public static ArrayList getSenses(IndexWord word) throws JWNLException{
		/*
		 * Returns an arraylist of all passed Indexword's senses
		 */
		IndexWord wordInd = word; //wordnet.getIndexWord(word.getPOS(), word.getLemma());


		//System.out.println("Available POS for word "+wordInd.getLemma()+" "+wordInd.getPOS());
		//String something = wordInd.getPOS().getLabel();
		//System.out.println(something);

		Synset[] senses = wordInd.getSenses();
		ArrayList sensesContainer = new ArrayList();
		for(int i = 0; i < senses.length;i++){
			//ADDED BY DAN TO RETURN SYNSET OBJ INSTEAD OF LEMMAS SO THAT YOU CAN DO MORE STUFF WITH THEM
			sensesContainer.add(senses[i]); 
		}
		if(sensesContainer!=null){
			return sensesContainer;
		}
		return null;
	}

//	This method looks for any possible relationship
	public static Relationship getRelationship (IndexWord start, IndexWord end, PointerType type) throws JWNLException {
		// All the start senses
		Synset[] startSenses = start.getSenses();
		// All the end senses
		Synset[] endSenses = end.getSenses();
		// Check all against each other to find a relationship
		for (int i = 0; i < startSenses.length; i++) {
			for (int j = 0; j < endSenses.length; j++) {
				RelationshipList list = RelationshipFinder.getInstance().findRelationships(startSenses[i], endSenses[j], type);
				if (!list.isEmpty())  {
					System.out.println("relation list is empty");
					return (Relationship) list.get(i);  
				}
			}
		}
		return null;
	}

	//Get the IndexWord object for a String and POS
	public static IndexWord getWord(POS pos, String s) throws JWNLException {
		IndexWord word = wordnet.getIndexWord(pos,s);
		return word;
	}
	
	//check what POS the synset is and accordingly get target synsets for that source synset syn_
	public static String getTargetWords(Synset syn_) throws JWNLException{
		PointerTargetNodeList relatedList=null;
		if((syn_.getPOS() == POS.ADJECTIVE)){
		relatedList = PointerUtils.getInstance().getSynonyms(syn_);
		} else if (syn_.getPOS() == POS.NOUN){
			relatedList = PointerUtils.getInstance().getDirectHypernyms(syn_);
		} else if (syn_.getPOS() == POS.VERB){
			relatedList = PointerUtils.getInstance().getEntailments(syn_);
		}
		
		Iterator i = relatedList.iterator();
		//System.out.println("relatedList size "+relatedList.size());
		while (i.hasNext()) {
		  PointerTargetNode related = (PointerTargetNode) i.next();
		  Synset s = related.getSynset();
		  //System.out.println(syn_.getPOS()+" TARGET SYNSETS ->"+s);
		  System.out.println("RELATED TARGET WORD "+s.getWord(0).getLemma());
		  return s.getWord(0).getLemma();
		}
		return null;
	}


//	END 
}
