/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package dict;

import edu.smu.tspell.wordnet.NounSynset;
import edu.smu.tspell.wordnet.Synset;
import edu.smu.tspell.wordnet.SynsetType;
import edu.smu.tspell.wordnet.WordNetDatabase;
import edu.smu.tspell.wordnet.impl.file.synset.NounReferenceSynset;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 *
 * @author chepa
 */
public class WNDictionary implements IDictionary {

	private static WNDictionary wndict;
	private WordNetDatabase wnDatabase;

	private WNDictionary() {
		wnDatabase = WordNetDatabase.getFileInstance();
	}

	public static IDictionary getInstance() {
		if (wndict == null) {
			wndict = new WNDictionary();
		}
		return wndict;
	}

	public boolean isSimilarTo(String str, String candidate, SynsetType type) {
		Synset[] arr = wnDatabase.getSynsets(str);
		if (arr == null) {
			return false;
		}
		for (Synset set : arr) {
			if (!set.getType().equals(type)) {
				continue;
			}
			for (String s : set.getWordForms()) {
				if (s.equals(candidate)) {
					return true;
				}
			}
		}
		return false;
	}

	public String getRootVerb(String verb) {
		String[] candidates = wnDatabase.getBaseFormCandidates(verb, SynsetType.VERB);
		if (candidates.length == 1) {
			return candidates[0];
		} else if (candidates.length == 0) {
			return verb;
		}
		for (String candidate : candidates) {
			for (Synset set : wnDatabase.getSynsets(candidate, SynsetType.VERB)) {
				if (set.getType().equals(SynsetType.VERB)) {
					return candidate;
				}
			}
		}
		return null;
	}

	private void collectHypernyms(String phrase, Set<String> setHyper, int levelLim) {
		if (levelLim <= 0) {
			return;
		}
		Synset[] synonyms = wnDatabase.getSynsets(phrase, SynsetType.NOUN);
		if (synonyms == null) {
			return;
		}
		for (Synset s : synonyms) {
			NounSynset n = (NounReferenceSynset) s;
			for (String sForm : n.getWordForms()) {
				if (sForm.equals(phrase)) {
					for (NounSynset syn : n.getHypernyms()) {
						for (String hyp : syn.getWordForms()) {
							if (setHyper.contains(hyp)) {
								continue;
							}
							setHyper.add(hyp);
							collectHypernyms(hyp, setHyper, levelLim - 1);
						}
					}
					return;
				}
			}
		}
	}

	public Collection<String> getHypernyms(String phrase) {
		phrase = phrase.replaceAll("[_]", " ");
		Set<String> setHyperNyms = new HashSet<String>();
		collectHypernyms(phrase, setHyperNyms, 1);
		return setHyperNyms;
	}

	private void collectHyponyms(String phrase, Set<String> setHypo, int levelLim) {
		if (levelLim <= 0) {
			return;
		}
		Synset[] synonyms = wnDatabase.getSynsets(phrase, SynsetType.NOUN);
		if (synonyms == null) {
			return;
		}
		for (Synset s : synonyms) {
			NounSynset n = (NounReferenceSynset) s;
			for (String sForm : n.getWordForms()) {
				if (sForm.equals(phrase)) {
					for (NounSynset syn : n.getHyponyms()) {
						for (String hypo : syn.getWordForms()) {
							if (setHypo.contains(hypo)) {
								continue;
							}
							setHypo.add(hypo);
							collectHyponyms(hypo, setHypo, levelLim - 1);
						}
					}
					return;
				}
			}
		}
	}

	public Collection<String> getHyponyms(String phrase) {
		phrase = phrase.replaceAll("[_]", " ");
		Set<String> setHypoNyms = new HashSet<String>();
		collectHyponyms(phrase, setHypoNyms, 1);
		return setHypoNyms;
	}

	public Collection<String> getMeronyms(String phrase) {
		phrase = phrase.replaceAll("[_]", " ");
		Set<String> setMeroNyms = new HashSet<String>();
		Synset[] synonyms = wnDatabase.getSynsets(phrase, SynsetType.NOUN);
		if (synonyms == null) {
			return setMeroNyms;
		}
		for (Synset s : synonyms) {
			NounSynset n = (NounReferenceSynset) s;
			for (String sForm : n.getWordForms()) {
				if (sForm.equals(phrase)) {
					for (NounSynset syn : n.getMemberMeronyms()) {
						for (String mero : syn.getWordForms()) {
							setMeroNyms.add(mero);
						}
					}
					return setMeroNyms;
				}
			}
		}
		return setMeroNyms;
	}

	public Collection<String> getHolonyms(String phrase) {
		phrase = phrase.replaceAll("[_]", " ");
		Set<String> setHoloNyms = new HashSet<String>();
		Synset[] synonyms = wnDatabase.getSynsets(phrase, SynsetType.NOUN);
		if (synonyms == null) {
			return setHoloNyms;
		}
		for (Synset s : synonyms) {
			NounSynset n = (NounReferenceSynset) s;
			for (String sForm : n.getWordForms()) {
				if (sForm.equals(phrase)) {
					for (NounSynset syn : n.getMemberHolonyms()) {
						for (String holo : syn.getWordForms()) {
							setHoloNyms.add(holo);
						}
					}
					return setHoloNyms;
				}
			}
		}
		return setHoloNyms;
	}

	public Collection<String> getSynonyms(String phrase) {
		phrase = phrase.replaceAll("[_]", " ");
		Synset[] synonyms = wnDatabase.getSynsets(phrase);
		List<String> lstSynonyms = new ArrayList<String>();
		for (Synset s : synonyms) {
			for (String syn : s.getWordForms()) {
				lstSynonyms.add(syn);
			}
		}
		return lstSynonyms;
	}

	public Collection<String> getSynonyms(String phrase, SynsetType type) {
		phrase = phrase.replaceAll("[_]", " ");
		Synset[] synonyms = wnDatabase.getSynsets(phrase, type);
		List<String> lstSynonyms = new ArrayList<String>();
		for (Synset s : synonyms) {
			for (String syn : s.getWordForms()) {
				lstSynonyms.add(syn);
			}
		}
		return lstSynonyms;
	}
}
