import java.io.*;
import java.util.*;
import javax.swing.*;
import java.awt.*;

public class TwentyQuest{

//the following is the database of possible answers
//the name of each Thing is the actual possible answer,
//the contents of the set are the attributes of the particular answer
	
	public static ArrayList possibilities = new ArrayList();;	//contains the current possible answers
	public static ArrayList questions = new ArrayList();	//current remaining questions to pick from


//loads all of the data when the program starts
	public static void loadData(String a){
		try{
			File fd = new File(a);	//input file
			BufferedReader rd = new BufferedReader(new FileReader(fd));
			StringTokenizer aline;
			String next = rd.readLine();

			while (!next.equals("questions") && !next.equals(null)){
				aline = new StringTokenizer(next);
				next = aline.nextToken(",");
				Thing tempThing = new Thing(next, new HashSet());
				while (aline.hasMoreTokens()){
					next = aline.nextToken(",");
					tempThing.addAttribute(next);
				}
				possibilities.add(tempThing);
				next = rd.readLine();
			}
			next = rd.readLine();
			while (next!=null){
				aline = new StringTokenizer(next);
				String quest = aline.nextToken(",");
				String att = aline.nextToken(",");
				questions.add(new Question(quest, att));
				next = rd.readLine();
			}
			rd.close();
		} catch (FileNotFoundException e) {		//catches some errors
			System.out.println("Error: file not found.");
		} catch (IOException e) {
			System.out.println("Error: incorrect input.");
		}
	}

//returns a HashSet containing all of the remaining useful attributes
	public static HashSet getAllAttributes(){
		Iterator it;
		Thing tempThing;					//used to first obtain a new Thing
		HashSet temp;						//temp HashSet to go through list of possibilites
		HashSet result = new HashSet();		//will contain all of the attributes
		for (int x= 0; x < possibilities.size(); x++){
			tempThing = (Thing)possibilities.get(x);
			temp = tempThing.getAttributes();
			it = temp.iterator();
			for (int y= 0; y < temp.size(); y++){
				String nextAtt = (String)it.next();
				result.add(nextAtt);
			}
		}
		return result;
	}

	public static HashSet getCommonAtt(){
		Thing tempThing = (Thing)possibilities.get(0);
		HashSet tempAtt = tempThing.getAttributes();
		HashSet result = (HashSet)tempAtt.clone();
		Iterator it;
		
		for (int x = 1; x < possibilities.size(); x++){
			HashSet tempSet = new HashSet();
			tempThing = (Thing)possibilities.get(x);
			tempAtt = tempThing.getAttributes();
			it = result.iterator();
			while (it.hasNext()){
				String next = (String)it.next();
				if (tempAtt.contains(next)){
					tempSet.add(next);
				}
			}
			result = tempSet;
		}
		/*System.out.println("");
		it = result.iterator();
		for (int x = 0; x < result.size(); x++){
			String next = (String)it.next();
			System.out.println("" + next);
		}
		System.out.println("");*/
		return tempAtt;
	}

//updates all of the useful questions
	public static void updateQuest(HashSet a){
		ArrayList temp = new ArrayList();
		HashSet common = getCommonAtt();
		Question nextQuest;
		for (int x = 0; x < questions.size(); x++){
			nextQuest = (Question)questions.get(x);
			Iterator it = a.iterator();
			for (int y = 0; y < a.size(); y++){
				String tempStr = (String)it.next();
				if (nextQuest.hasAttribute(tempStr)){
					temp.add(nextQuest);
				}
			}
		}
		int y = 0;
		while (y < temp.size()){
			nextQuest = (Question)temp.get(y);
			String nextAtt = nextQuest.getAttribute();
			if (common.contains(nextAtt)){
				temp.remove(y);
			}else{
				y++;
			}
		}
		questions = temp;
	}

//used to randomly pick a question
//variable 'a' represents the current size of ArrayList 'questions'
	public static int randUpTo(int a){
		Random randy = new Random();
		return Math.abs(randy.nextInt()%a);
	}

	public static void twentyQuestions(){
		int count = 0;							//counts number of questions
		
		while ((count < 20)&&(questions.size() > 0)
										&&(possibilities.size() > 1)){	//go through the 20 questions
			ArrayList temp = new ArrayList();		//temporarily holds new possibilities
			int index = randUpTo(questions.size());
			Question nextQuest = (Question)questions.get(index);
			String answer = JOptionPane.showInputDialog(nextQuest.getQuestion() + "\n" + "(yes/no)").toLowerCase();
			String attribute = nextQuest.getAttribute();
			Thing tempThing;

			while (!(answer.equals("yes"))&&!(answer.equals("y"))&&!(answer.equals("no"))&&!(answer.equals("n"))){
				answer = JOptionPane.showInputDialog(nextQuest.getQuestion() + "\n" + "Please answer yes or no").toLowerCase();
			}
			
			if ((answer.equals("yes"))||(answer.equals("y"))){
				for (int x = 0; x < possibilities.size(); x++){
					tempThing = (Thing)possibilities.get(x);	
					if (tempThing.hasAttribute(attribute)){
						temp.add(tempThing);
						System.out.println("" + tempThing.getName());
					}
				}
				System.out.println("");
			} else if ((answer.equals("no"))||(answer.equals("n"))){
				for (int x = 0; x < possibilities.size(); x++){
					tempThing = (Thing)possibilities.get(x);
					if (!(tempThing.hasAttribute(attribute))){
						temp.add(tempThing);
						System.out.println("" + tempThing.getName());
					}
				}
				System.out.println("");
			}
			
			if (questions.size() > 0){
				questions.remove(index);
			}

			possibilities = temp;
			updateQuest(getAllAttributes());
			count++;
		}
	}

	public static void main(String[] args){
		Thing answerTh;
		String answer;

		loadData(args[0]);
		twentyQuestions();

		if (possibilities.size() == 1){
			answerTh = (Thing)possibilities.get(0);
			answer = answerTh.getName();
			JOptionPane.showMessageDialog(new JFrame(),"My guess is that you are thinking of: " + answer);
		}else{
			for(int x = 0; x < possibilities.size(); x++){
				answerTh = (Thing)possibilities.get(x);
				answer = answerTh.getName();
				String response = JOptionPane.showInputDialog("Is it: " + answer + "? (y/n)").toLowerCase();
				if (response.equals("yes")||response.equals("y")){
					JOptionPane.showMessageDialog(new JFrame(),"Sweet!!");
					break;
				}else{
					JOptionPane.showMessageDialog(new JFrame(),"Whoops!!");
				}
			}
		}
		System.exit(0);
	}
}