/home/caleb/ASDV-Java/Semester 3/Assignments/MP6_CalebFontenot/src/main/java/edu/slcc/asdv/caleb/mp6_calebfontenot/CircularList.java
package edu.slcc.asdv.caleb.mp6_calebfontenot;

/**
 *
 * @author Markou
 */
public class CircularList<T extends Comparable<T>> {

    Node<T> head;

    public class Node< T extends Comparable<T>>
            implements Comparable<Node<T>> {

        private T t;

        public void set(T t)
        {
            this.t = t;
        }

        public T get()
        {
            return t;
        }
        Node<T> next;

        @Override
        public int compareTo(Node<T> o)
        {
            return this.t.compareTo(o.get());
        }
    }

    /**
     *
     * @param t
     */
    public void add(Object t)
    {
        Node<T> temp = new Node();
        temp.set((T) t);

        if (head == null) {
            head = temp;
            head.next = head;
        } else {
            Node<T> temp2 = head;
            do {
                temp2 = temp2.next;
            } while (temp2.next != head);
            temp.next = head;
            temp2.next = temp;
        }
    }

    /**
     *
     * @return
     */
    private int getSize()
    {
        if (head == null) {
            return 0;
        }
        Node<T> temp = head;
        int count = 0;
        do {
            temp = temp.next;
            count++;
        } while (temp != head);

        return count;
    }
    ////////////////////////////////////////////////////////

    public void addAt(Object t, int pos)
    {
        if (pos < 0 || pos > getSize()) {
            return;
        }

        Node<T> temp = new Node();
        temp.set((T) t);

        if (head == null) {
            add(t);
        } else if (pos == 0) {
            int oldSize = getSize();
            Node<T> currentHead = head;
            temp.next = head;
            head = temp;
            // Set the node at the end of the list to point back to the new head.
            Node<T> pointer = head;
            for (int i = 0; i < oldSize; ++i) {
                pointer = pointer.next;
            }
            pointer.next = temp;
        } else {
            // Iterate to the desired position
            Node<T> pointer = head;
            for (int i = 0; i < pos -1; ++i) {
                pointer = pointer.next;
            }
            temp.next = pointer.next;
            pointer.next = temp;
        }
    }
//////////////////////////////////////////////////////////////
/**
 * removes the last node
 */
    public void remove()
    {
        Node<T> pointer = head;
        for (int i = 0; i < this.getSize() - 2; ++i) {
             pointer = pointer.next;
        }
        pointer.next = head;
    }
//////////////////////////////////////////////////////////////
/**
 * removes a specific object from the list
 */
    public boolean remove(Object t)
    {
        Node<T> pointer = head;
        boolean isObjectRemoved = false;
        do {
            boolean eval = pointer.next.t.equals(t);
            if (eval) {
                isObjectRemoved = true;
                pointer.next = pointer.next.next;
                break;
            } else {
                pointer = pointer.next;
            }
        } while (pointer != head);
        return isObjectRemoved;
    }
//////////////////////////////////////////////////////////////

    public void removeAt(int pos)
    {
        Node<T> pointer = head;
        for (int i = 0; i < pos; ++i) {
            boolean eval = i == pos - 1;
            if (eval) {
                pointer.next = pointer.next.next;
                break;
            } else {
                pointer = pointer.next;
            }
        }
    }

    public void print()
    {

        if (head == null) {
            return;
        }
        Node<T> temp = head;
        int elementNum = 0;
        do {
            System.out.print(++elementNum + ": ");
            System.out.println(temp.get().toString());
            temp = temp.next;
        } while (temp != head);

    }

    public static void main(String... ar)
    {
        CircularList<String> list = new CircularList();
        list.add("Hello");
        list.add("World");
        list.add("one");
        String removeMe = "two";
        list.add(removeMe);
        list.add("three");
        list.add("four");
        list.add("five");
        list.add("six");
        list.add("seven");
        list.print();
        System.out.println("-------------");
        System.out.println("Remove the last object:");
        list.remove();
        list.print();
        System.out.println("-------------");
        System.out.println("Remove \"two\"");
        list.remove(removeMe);
        list.print();
        System.out.println("-------------");
        System.out.println("Remove the 3rd element:");
        list.removeAt(2);
        list.print();
        System.out.println("-------------");
        System.out.println("Add an element to the beginning");
        list.addAt("Earth", 0);
        list.print();
        System.out.println("-------------");
        System.out.println("Add an element named \"potato\" in the 4th position:");
        list.addAt("potato", 3);
        list.print();
    }

}