// Guide to Data Structures
// Section 10.9
// Copyright 2018, by J.T. Streib and T. Soma

import java.util.*;
import java.io.*;
class PrinterPriorityQueue {
public static void main(String[] args) throws IOException {
  
 PriorityQueueClassGeneric<FileWithPriority> printQueue
     = new PriorityQueueClassGeneric<FileWithPriority>();
  
 insertItemToPrintQueue(printQueue);   

 System.out.println("Printer Queue: ");
 for(int i=0; i<5; i++)
    System.out.println(printQueue.removeMin().toString());
}    

public static void insertItemToPrintQueue(PriorityQueueClassGeneric
               <FileWithPriority> printQueue) throws IOException
{
 String fileName, rank;
 Scanner inFile = new Scanner(new File("f:files.txt"));
 while(inFile.hasNextLine()) {
    fileName = inFile.nextLine();
    rank = inFile.nextLine();
    FileWithPriority file = new FileWithPriority(fileName, rank);
    printQueue.insertItem(file);
 }
}
}


public class FileWithPriority implements Comparable<FileWithPriority> {
private String fileName;
private String ranking;

public FileWithPriority(String fileName, String ranking) {
 setFileName(fileName);
 setRanking(ranking);
}

public String getFileName() {
 return fileName;
}

public String getRanking() {
 return ranking;
}

public void setFileName(String fileName) {
 this.fileName = fileName;
}

public void setRanking(String ranking) {
 this.ranking = ranking;
}

public int compareTo(FileWithPriority otherFile) {
 int result;
 if(getRankingNumber(ranking)
    < getRankingNumber(otherFile.getRanking()))
    result = -1;
 else
    if(getRankingNumber(ranking)
       > getRankingNumber(otherFile.getRanking()))
       result = 1;
    else
       result = 0;
 return result;
}
   
private int getRankingNumber(String ranking) {
 int rankingNumber;
 if(ranking.equals("Principal"))
    rankingNumber = 1;
 else
    if(ranking.equals("Soloist"))
       rankingNumber = 2;
    else
       if(ranking.equals("Corps de Ballet"))
          rankingNumber = 3;
       else
          if(ranking.equals("Apprentice"))
             rankingNumber = 4;
          else
             rankingNumber = 5;
 return rankingNumber;
}

public String toString() {
 return ("File name: " + fileName + " sent by " + ranking);
}
}


public class PriorityQueueClassGeneric<T extends Comparable<T>> {
private final int n = 20;
private T[] array;
private int size;

public PriorityQueueClassGeneric() {
  array=(T[]) new Comparable[n];
  size = 0;
}

public void insertItem(T x) {
 array[size] = x;
 moveUp();
 size++;
}

private void moveUp() {
 int child = size;
 int parent = (child-1)/2;
 T temp = array[child];
 while(child > 0 && temp.compareTo(array[parent]) < 0) {
    array[child] = array[parent];
    child = parent;
    parent = (child-1)/2;
 }
 array[child]=temp;
}
   
public T removeMin() {
 T min=array[0];
 array[0]=array[--size];
 moveDown();
 return min;
}

public T peekMin() {
 return array[0];
}

public void copyQueue(T[] otherArray) {
 otherArray=(T[]) new Comparable[n];
 for(int i=0; i<size; i++)
    otherArray[i] = array[i];
}

private void moveDown() {
 boolean flag = false;
 T smallest = null;
 int parent = 0;
 int child = 2*parent+1;
 T temp = array[parent];
 while(child < size && !flag) {
    smallest = array[child];
    if(child+1<size && array[child+1].compareTo(array[child])<0)
       smallest = array[++child];
    if(smallest.compareTo(temp) < 0) {
       array[parent] = smallest;
       parent = child;
    }
    else
       flag = true;
    child = 2*parent+1;
 }
 array[parent] = temp;
}
}