import java.util.Set;
import java.util.TreeSet;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.Collection;

class Employee {
  private int hours;
  public Employee(int hours) {
    this.hours = hours;
  }
  public int getHours() {
    return hours;
  }
  public double getPay() {
    return 12.0 * getHours();
  }
  public String toString() {
    return "Employee hoi polloi";
  }
}

class SuperEmployee extends Employee {
  public SuperEmployee(int hours) {
    super(hours);
  }
  public double getPay() {
    return 18.0 * getHours() + 80.0;
  }
  public String toString() {
    return "Super-super";
  }
}

class Manager extends Employee {
  private int numSubordinates;
  public Manager(int hours, int numSubs) {
    super(hours);
    numSubordinates = numSubs;
  }
  public int getNumSubs() {
    return numSubordinates;
  }
  public double getPay() {
    return 100.0 * getNumSubs() + 20.0 * getHours();
  }
  public String toString() {
    return "The incridible manager";
  }
}

class Guard extends Employee {
  private double dangerFactor;
  public Guard(int hours, double df) {
    super(hours);
    dangerFactor = df;
  }
  public double getDangerFactor() {
    return dangerFactor;
  }
  public double getPay() {
    return 80.0 * getDangerFactor() + 16.0 * getHours();
  }
  public String toString() {
    return "The valiant captain";
  }
}

public class Payment3 {

  private static Collection<Employee>
    getLuckyList(Collection<Employee> staff, double total) {
      Set<Employee> luckies = new HashSet<Employee>();
      // Pay the Super dudes first:
      for (Employee e : staff) {
        if (e instanceof SuperEmployee) {
          if (total > e.getPay()) {
            total -= e.getPay();
            luckies.add(e);
          }
        }
      }
      // Now pay the hoi-polloy:
      for (Employee e : staff) {
        if (!luckies.contains(e)) {
          if (total > e.getPay()) {
            total -= e.getPay();
            luckies.add(e);
          }
        }
      }
      return luckies;
    }

  private static double getPayroll(Collection<Employee> staff) {
    double payroll = 0.0;
    for (Employee e : staff) {
      payroll += e.getPay();
    }
    return payroll;
  }

  private static Collection<Employee> createMockStaff() {
//    Collection<Employee> c = new TreeSet<Employee>();
    Collection<Employee> c = new LinkedList<Employee>();
    Employee e1 = new Employee(40);
    c.add(e1);
    Employee e2 = new Employee(35);
    c.add(e2);
    Employee m = new Manager(40, 2);
    c.add(m);
    Employee g1 = new Guard(30, 1.6);
    c.add(g1);
    Employee g2 = new Guard(40, 1.2);
    c.add(g2);
    Employee s = new SuperEmployee(35);
    c.add(s);
    return c;
  }

  public static void main(String args[]) {
    Collection<Employee> staff = createMockStaff();
    System.out.println("Pay = " + getPayroll(staff));
    for (Employee e : getLuckyList(staff, 2000.0)) {
      System.out.println(e);
    }
  }
}
