import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Scanner;

/**
 * An implementation of the BagInterface that uses a human being (the user) to
 * control the bag and answer all questions about it. The human is responsible
 * for making sure that everything works as it should. An object of this class
 * simply passes the requests on to the user, and returns the responses to the
 * client.
 * <p>
 * To simplify the implementation, only Strings are allowed in the HumanBag.
 * <p>
 * Requests to the user are prefixed with greater-than signs (>>>).
 *
 * @author Mark Young (A00000000)
 */
public class HumanBag implements Bag<String> {

    private Scanner human = new Scanner(System.in);

    @Override
    public int size() {
        System.out.print(">>> How many items are in the bag? ");
        int numInBag = human.nextInt();
        human.nextLine();
        return numInBag;
    }

    @Override
    public boolean isEmpty() {
        System.out.print(">>> Is the bag empty? ");
        String answer = human.next().toUpperCase();
        human.nextLine();
        return answer.startsWith("Y");
    }

    @Override
    public boolean add(String newEntry) {
        System.out.println(">>> Add a " + newEntry + " to the bag. ");
        System.out.print(">>> Type NO if you can't, "
                + "or press ENTER when you're done: ");
        String answer = human.nextLine().toUpperCase();
        return !answer.equals("NO");
    }

    @Override
    public String remove() {
        System.out.println(">>> Remove something from the bag. ");
        System.out.print(">>> Tell me what it is "
                + "(leave blank if there was nothing in the bag): ");
        String answer = human.nextLine();
        if ("".equals(answer)) {
            return null;
        } else {
            return answer;
        }
    }

    @Override
    public boolean remove(Object anEntry) {
        System.out.println(">>> Remove a " + anEntry + " from the bag. ");
        System.out.print(">>> Type NO if you can't, "
                + "or press ENTER when you're done: ");
        String answer = human.nextLine().toUpperCase();
        return !answer.equals("NO");
    }

    @Override
    public void clear() {
        System.out.println(">>> Dump everything out of the bag.");
        System.out.print(">>> Press ENTER when you're done....");
        human.nextLine();
    }

    @Override
    public int getFrequency(String anEntry) {
        System.out.print(">>> How many " + anEntry + "s are in the bag? ");
        int numInBag = human.nextInt();
        human.nextLine();
        return numInBag;
    }

    @Override
    public boolean contains(Object anEntry) {
        System.out.print(">>> Is there a " + anEntry + " in the bag? ");
        String answer = human.next().toUpperCase();
        human.nextLine();
        return answer.startsWith("Y");
    }

    @Override
    public String[] toArray() {
        int inBag = this.size();
        String[] contents = new String[inBag];
        if (inBag > 0) {
            System.out.println(">>> Tell me what each of the items is.");
            System.out.println(">>> Enter one item per line "
                    + "until you're done.");
            for (int i = 0; i < inBag; ++i) {
                System.out.print(" >> item #" + (i + 1) + " >> ");
                contents[i] = human.nextLine();
            }
            System.out.println(">>> Thank you!");
            System.out.println(">>> Make sure all those items are "
                    + "still/back in the bag.");
            System.out.print(">>> Press ENTER when you're ready....");
            human.nextLine();
        }
        return contents;
    }

    @SuppressWarnings("unchecked")
    @Override
    public <T> T[] toArray(T[] starter) {
        int mySize = this.size();
        if (starter.length < mySize) {
            starter = Arrays.copyOf(starter, mySize);
        }
        String[] myContents = toArray();
        for (int i = 0; i < mySize; ++i) {
            starter[i] = (T)myContents[i];
        }

        // terminate with a null, if possible
        if (starter.length > mySize) {
            starter[mySize] = null;
        }
        return starter;
    }

    @Override
    public Iterator<String> iterator() {
        List<String> myList = Arrays.asList(toArray());
        return myList.iterator();
    }

}
