package Sorting;

import java.time.Duration;
import java.time.Instant;
import java.lang.Integer;

/**
 * This is an abstract class, its subclasses will inherit its methods and instance
 * fields. Any abstract methods will have to be implemented in the subclasses.
 */
abstract class Sorter {

    protected String sortType;
    protected Integer[] numbers;
    protected long comparisonsUsed = 0;
    protected long writesUsed=0;

    public Sorter(String st, String filename){
        sortType=st;
        RandomNumberFileReader reader = new RandomNumberFileReader(filename);
        numbers = new Integer[reader.getNumbers().size()];
        reader.getNumbers().toArray(numbers);
    }
   
    /**
     * An abstract sorting method. Each subclass will have to implement its own
     * version of this method.
     * @return A SortResult object holding number of comparisons, number of swaps, and the sorted array
     */
    abstract void sort();

    /**
     * A method to swap two elements of an array and increment the writesUsed counter.
     * @param a the index of the first element
     * @param b the index of the second element
     */
    void swap(int a, int b){
        int tmp = numbers[a];
        numbers[a] = numbers[b];
        numbers[b] = tmp;
        writesUsed+=2;
    }

    /**
     * A method to compare two integers and increment the comparisonsUsed counter.
     * @param a the first integer to be compared
     * @param b the second integer to be compared
     * @return a negative number if the first integer is smaller than the second, 0 if they are equal, and a positive number if the first integer is greater than the second.
     */
    int compare(int a, int b){
        comparisonsUsed++;
        return Integer.compare(a,b);
    }

    /**
     * Writes a value into an array at a specific index and increments the writesUsed counter.
     * @param array the array to be used
     * @param index the index to be written to
     * @param value the value to write
     */
    void writeToArray(Integer[] array, int index, int value){
        array[index]=value;
        writesUsed++;
    }

    /**
     * Measures how long the sort() function takes to run
     * @return returns a SortResult object with the name of the sorting algorithm used, the sorted array of numbers, the number of comparisons used to sort, and the number of writes to arrays used to sort
     */
    public SortResult measuredSort(){
        Instant start = Instant.now();
        this.sort();
        Instant end = Instant.now();
        Duration time = Duration.between(start,end);
        SortResult output = new SortResult(sortType, numbers, comparisonsUsed, writesUsed, time);
        return output;
    }

    
}