
import java.awt.Font;
import java.io.File;
import java.util.Random;
import java.util.Scanner;
import javax.swing.JOptionPane;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;

/**
 *
 * @author Bill Kraynek
 */
public class SingleLinkedListExample {

    public static void main(String[] args) {
        Node<String> stringHeader = new Node<String>();
        try {
            Scanner fileScanner = new Scanner(new File("src/SingleLinkedListExample.java"));
            fileScanner.useDelimiter("[^a-zA-Z]+");
            while (fileScanner.hasNext()) {
                String aWord = fileScanner.next();
                Node<String> p = stringHeader;
                while (p.next != null) {
                    if (aWord.equals(p.next.data)) {
                        break;
                    }// end if
                    p = p.next;
                }// end while
                if (p.next == null) {
                    p.next = new Node<String>(aWord, null);
                }// end if
            } // end while
        } catch (Exception e) {
            e.printStackTrace();
            ;
        } // end try/catch
        String out = "\t" + display(stringHeader,"\n");
        JTextArea outArea = new JTextArea(25, 40);
        outArea.setFont(new Font(Font.MONOSPACED, Font.BOLD, 15));
        outArea.setText(out);
        JOptionPane.showMessageDialog(null, new JScrollPane(outArea));
        Random random = new Random();
        Node<Integer> intHeader = new Node<Integer>();
        Node<Integer> q = intHeader;
        for (int i = 0; i < 10; i++) {
            q.next = new Node<Integer>(random.nextInt((100)));
            q = q.next;
        }// end for
        out = "Original list\n" + display(intHeader, " ") + "\n";
        out += "\n\tSum of ints\n\t" + sum(intHeader) + "\n\tMax of ints\n\t" + max(intHeader) + "\n\n";
        Node<Integer> reverse = new Node<Integer>(null,reverse(intHeader.next));
        out += "Reversed list using reverse\n" + display(reverse, " ") + "\n\n";
        out += "Original list after calling reverse\n" + display(intHeader, " ") + "\n\n";
        intHeader.next = reverse1(intHeader.next);
        out += "Reversed list using reverse1\n"+ display(intHeader, " ") + "\n\n";
        outArea.setText(out);
        JOptionPane.showMessageDialog(null, new JScrollPane(outArea));
    } // end main

    static <T> String display(Node<T> list, String separator) {
        if (list.next == null) {
            return "";
        }
        return list.next.data + separator + display(list.next,separator);
    }

    static int sum(Node<Integer> list) {
        if (list.next == null) {
            return 0;
        }
        return list.next.data + sum(list.next);
    }

    static <T extends Comparable<T>> T max(Node<T> list) {
        if (list.next.next == null) {
            return list.next.data;
        }
        T max = max(list.next);
        if (max.compareTo(list.next.data) < 0) {
            return list.next.data;
        }
        return max;
    }

    static <T> Node<T> reverse(Node<T> list) {
        if (list.next == null) {
            return new Node<T>(list.data, null);
        }// end if
        Node<T> reverseList = reverse(list.next);
        Node<T> copy = new Node<T>(list.data, null);
        Node<T> p = reverseList;
        while (p.next != null) {
            p = p.next;
        }
        p.next = copy;
        return reverseList;
    }

    static <T> Node<T> reverse1(Node<T> list) {
        if (list.next == null) {
            return list;
        }// end if
        Node<T> temp = list.next;
        list.next = null;
        Node<T> reverseList = reverse1(temp);
        temp.next = list;
        return reverseList;
    }
}

class Node<T> {

    T data;
    Node<T> next;

    Node() {
    }

    Node(T data) {
        this.data = data;
    } // end

    Node(T data, Node<T> next) {
        this.data = data;
        this.next = next;
    } // end

    public String toString() {
        return data + "";
    } // end toString
} // end Node


