// This program is copyright VUW.
// You are granted permission to use it to construct your answer to a XMUT103 assignment.
// You may not distribute it in any other way without permission.

/* Code for XMUT103 - 2026T1, Assignment 4
 * Name:
 * Username:
 * ID:
 */

import ecs100.*;
import java.util.*;
import java.io.*;
import java.nio.file.*;

/** Analysing and Measuring Sets
 *  Measuring how long it takes to find the number of unique words
 *  within a given file of words,
 *  using 3 different types of Collections (ArrayList, HashSet, and TreeSet)
 */
public class VocabularyMeasure{

    /** Set up the GUI */
    public void setupGUI(){
        UI.addButton("All", this::analyseAll);
        UI.addButton("Quit", UI::quit);
        UI.setDivider(1.0);
    }

    public void analyseAll(){
        for (String fname : List.of(
            "711-MouseBirdSausage.txt",
            "100k-AnneOfGreenGables.txt",
            "500k-WarAndPeace.txt",
            "1M-Clarissa.txt",
            "2M-cyrus.txt",
            "5M-all.txt"
            )){
            analyse("texts/"+fname);
        }
        UI.println("All done");
    }

    public void analyse(String fname){
        UI.printf("======================================\n%s\n", fname);  
        analyseHSet(fname);
        analyseTSet(fname);
        analyseList(fname);
    }

    /** Count words and distinct words using a HashSet */
    public void analyseHSet(String fname){
        int count = 0;
        Set<String> vocab = new HashSet<String>();
        try{
            Scanner sc = new Scanner (Path.of(fname));
            long start = System.currentTimeMillis();
            while (sc.hasNext()){
                String word = sc.next();
                count++;
                vocab.add(word);
            }
            double time = (System.currentTimeMillis()-start)/1000.0;
            sc.close();
            UI.printf("HSet: Time  = %6.3fs,  Words = %,10d  Vocab = %,d\n", 
                time, count, vocab.size());
        }catch(IOException e){UI.println("bad"+e);}
    }

    /** Count words and distinct words using a TreeSet */
    public void analyseTSet(String fname){
        int count = 0;
        Set<String> vocab = new TreeSet<String>();
        try{
            Scanner sc = new Scanner (Path.of(fname));
            long start = System.currentTimeMillis();
            while (sc.hasNext()){
                String word = sc.next();
                count++;
                vocab.add(word);
            }
            double time = (System.currentTimeMillis()-start)/1000.0;
            sc.close();
            UI.printf("TSet: Time  = %6.3fs,  Words = %,10d  Vocab = %,d\n", 
                time, count, vocab.size());
        }catch(IOException e){UI.println("bad"+e);}
    }

    /** Count words and distinct words using a List */
    public void analyseList(String fname){  
        System.gc();
        int count = 0;
        List<String> vocab = new ArrayList<String>();
        try{
            Scanner sc = new Scanner (Path.of(fname));
            long start = System.currentTimeMillis();
            while (sc.hasNext()){
                String word = sc.next();
                count++;
                if(!vocab.contains(word)){vocab.add(word);}
            }
            double time = (System.currentTimeMillis()-start)/1000.0;
            sc.close();
            UI.printf("List: Time  = %6.3fs,  Words = %,10d  Vocab = %,d\n", 
                time, count, vocab.size());

        }catch(IOException e){UI.println("bad"+e);}
    }

    public static void main(String[] args){
        new VocabularyMeasure().setupGUI();
    }
}
