import java.io.FileNotFoundException;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.regex.Pattern;

public class DictSearcher {

	public static void main(String[] args) {

		if (args.length < 3) {
			System.err.println("Too few arguments!");
			System.err.println("Usage: DICTPATH LETTERS LENGTH [OFFSET:LETTER]");
			System.exit(1);
		}
		String dictFile = args[0];
		String allowedLetters = args[1];
		int allowedLength = Integer.parseInt(args[2]);

		int hintPos = -1;
		Character hintChar = null;
		if (args.length >= 4) {
			String[] hint = args[3].split(":");
			if (hint.length != 2 || hint[1].length() != 1)
				System.err.println("Wrong hint format!");

			hintChar = hint[1].toLowerCase().charAt(0);

			hintPos = Integer.parseInt(hint[0]);
			if (hintPos < 0)
				throw new NumberFormatException(
						"Negative positions are not allowed as hint");

		}

		SimpleDateFormat format = new SimpleDateFormat("HH:mm:ss");

		WortParser parser = null;
		try {
			parser = new WortParser(dictFile);
		} catch (FileNotFoundException e) {
			System.err.println("File not Found!");
			System.exit(1);
		}

		HashSet<Wort> dict = null;
		try {
			System.out
					.println("Reading dict file ("
							+ format.format(new Date(System.currentTimeMillis()))
							+ ")");
			dict = parser.readAll();
		} catch (IOException e) {
			System.err.println("Reading dict file failed!");
			System.exit(1);
		}

		System.out.println("Dict parsed ("
				+ format.format(new Date(System.currentTimeMillis())) + ")");
		System.out.println("Dict contains: " + dict.size() + " words");

		Collection<Wort> foundWords = searchWord(dict, allowedLetters,
				allowedLength);

		if (hintChar != null) {
			for (Iterator<Wort> it = foundWords.iterator(); it.hasNext();) {
				if (it.next().getWort().toLowerCase().charAt(hintPos) != hintChar)
					it.remove();
			}
		}

		System.out.println("Found " + foundWords.size() + " word/s ("
				+ format.format(new Date(System.currentTimeMillis())) + ")");

		for (Wort wort : foundWords) {
			System.out.println(wort.getWort());
		}

	}

	public static Collection<Wort> searchWord(Collection<Wort> dict,
			String letters, int length) {
		LinkedList<Wort> foundWords = new LinkedList<Wort>();
		for (Wort word : dict) {
			if (isMatch(word.getWort(), letters, length))
				foundWords.add(word);
		}
		return foundWords;
	}

	public static boolean isMatchRegex(String word, String letters, int length) {
		String regex = "(?i)(?u)[" + Pattern.quote(letters) + "]*";
		return ((word.length() == length) && word.matches(regex));

	}

	public static boolean isMatch(String word, String letters, int length) {

		if (word.length() != length)
			return false;

		char[] wordCharArray = word.toLowerCase().toCharArray();
		ArrayList<Character> lettersArray = new ArrayList<Character>();
		for (Character lc : letters.toLowerCase().toCharArray()) {
			lettersArray.add(lc);
		}

		boolean found;
		for (Character wc : wordCharArray) {
			found = false;
			for (Iterator<Character> it = lettersArray.iterator(); it.hasNext();) {
				if (wc.equals(it.next())) {
					it.remove();
					found = true;
					break;
				}
			}
			if (!found)
				return false;
		}
		return true;
	}
}
