package edu.columbia.cs.cs1007.datastructures;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;
/**
 * Demonstration of some set and map functionality.
 @author Julia Stoyanovich (jds2109@columbia.edu)
 * COMS 1007, Summer 2009
 */
public class SetAndMapDemo {
  
  public static enum DEAD_OR_ALIVE {DEAD, PLAYING_DEAD, ALIVE}
  
  public static void romeoAndJuliet() {

    String [] mCharacters = {"Romeo""Montague""Lady Montague""Mercutio"};
    String [] cCharacters = {"Juliet""Capulet""Lady Capulet""Tybalt"};
    Set<String> theCast = new HashSet<String>();
    Set<String> theMontagues = new HashSet<String>();
    Set<String> theCapulets = new HashSet<String>();

    // link each character to his/her clan
    Map<String, Set<String>> clanMap = new TreeMap<String, Set<String>>();
    // link each character to his/her current vital status
    Map<String, DEAD_OR_ALIVE> vitalsMap = new HashMap<String,DEAD_OR_ALIVE>();
    
    // place the Montagues
    for (String name : mCharacters) {
      theMontagues.add(name);
      clanMap.put(name, theMontagues);
      vitalsMap.put(name, DEAD_OR_ALIVE.ALIVE);
    }
    
    // place the Capulets
    for (String name : cCharacters) {
      theCapulets.add(name);
      clanMap.put(name, theCapulets);
      vitalsMap.put(name, DEAD_OR_ALIVE.ALIVE);
    }

    // print members of Juliet's clan
    if(clanMap.containsKey("Juliet")) {
      System.out.print("Juliet's clan: ");
      Iterator<String> clanIter = clanMap.get("Juliet").iterator();
      while (clanIter.hasNext()) {
        System.out.print(clanIter.next() " ");
      }
      System.out.println("");
    }

    // print members of Romeo's clan
    if(clanMap.containsKey("Romeo")) {
      System.out.print("Romeo's clan: ");
      Iterator<String> clanIter = clanMap.get("Romeo").iterator();
      while (clanIter.hasNext()) {
        System.out.print(clanIter.next() " ");
      }
      System.out.println("");
    }
    
    // print members of Hamlet's clan
    if(clanMap.containsKey("Hamlet")) {
      System.out.print("Hamlet's clan: ");
      Iterator<String> clanIter = clanMap.get("Hamlet").iterator();
      while (clanIter.hasNext()) {
        System.out.print(clanIter.next() " ");
      }
      System.out.println("");
    else {
      System.out.println("Hamlet does not have a clan.");
    }

    // all together now
    theCast.addAll(theMontagues);
    theCast.addAll(theCapulets);
    
    System.out.println("Print the cast in arbitrary order.");
    Iterator<String> iter = theCast.iterator();
    while (iter.hasNext()) {
      System.out.println("\t" + iter.next());
    }

    Set<String> sortedCast = new TreeSet<String>();
    sortedCast.addAll(theCast);
    
    System.out.println("Print the cast in sorted order by name.");
    iter = sortedCast.iterator();
    while (iter.hasNext()) {
      System.out.println("\t" + iter.next());
    }
    
    theCast.remove("Mercutio")// Tybalt kills Mercutio
    vitalsMap.put("Mercutio", DEAD_OR_ALIVE.DEAD);
    
    theCast.remove("Tybalt");   // Romeo kills Tybalt
    vitalsMap.put("Tybalt", DEAD_OR_ALIVE.DEAD);
    
    theCast.remove("Juliet");  // Juliet pretends to kill herself
    vitalsMap.put("Juliet", DEAD_OR_ALIVE.PLAYING_DEAD);  
    
    theCast.remove("Romeo");  // Romeo kills himself
    vitalsMap.put("Romeo", DEAD_OR_ALIVE.DEAD);  

    theCast.add("Juliet");    // Juliet wakes up
    vitalsMap.put("Juliet", DEAD_OR_ALIVE.ALIVE);  

    theCast.remove("Juliet");  // Juliet kills herself
    vitalsMap.put("Juliet", DEAD_OR_ALIVE.DEAD);  
    
    // list the characters who died
    Set<String> theDead = new TreeSet<String>(sortedCast);
    theDead.removeAll(theCast);
    iter = theDead.iterator();

    System.out.println("Print the dead");
    while (iter.hasNext()) {
      System.out.println("\tRIP " + iter.next());
    }
    
    System.out.println("Print the living");
    iter = theCast.iterator();
    while (iter.hasNext()) {
      System.out.println("\tLive in sorrow " + iter.next());
    }
    
    // print the cast together with vital status
    for (String key : vitalsMap.keySet()) {
      System.out.println(key + " is " + vitalsMap.get(key));
    }
    
    // what are the different vital statuses?
    for (DEAD_OR_ALIVE val : vitalsMap.values()) {
      System.out.println(val);
    }
    
    Set<DEAD_OR_ALIVE> vitalsSet = new HashSet<DEAD_OR_ALIVE>(vitalsMap.values());
    System.out.println("# distinct vitals " + vitalsSet.size());
    
    Set<Set<String>> clansSet = new HashSet<Set<String>>(clanMap.values());
    System.out.println("# distinct clans " + clansSet.size());
  }

  public static void main(String[] args) {
    romeoAndJuliet();    
  }
}