package l23_2;

public class SingleLinkedList {
	private SllNode head;
	private static boolean trace;
	
	// Note... default constructor initializes head to null... good nuff
	
	public static void startTrace() { trace=true; }
	public static void stopTrace() { trace=false; }
	
	public SllNode getTail() {
		return getTail(head);
	}
	
	private SllNode getTail(SllNode from) {
		if (from==null) return null;
		SllNode next=from.getNext();
		if (next==null) return from;
		return getTail(next);
	}
	
	public void pushHead(int payload) {
		SllNode newNode = new SllNode(payload);
		newNode.setNext(head);
		head=newNode;
		if (trace) 
			System.out.println("pushHead(" + payload + ") : " + toString());
	}
	
	public void pushTail(int payload) {
		if (head==null) head=new SllNode(payload);
		else getTail().setNext(new SllNode(payload));
		if (trace)
			System.out.println("pushTail(" + payload + ") : " + toString());
	}
	
	public void pushOrder(int payload) {
		if (head==null) head=new SllNode(payload);
		else if (payload < head.getPayload()) pushHead(payload);
		else pushOrder(payload,head);
		if (trace) 
			System.out.println("pushOrder(" + payload + ") : " + toString());
	}
	
	private void pushOrder(int payload,SllNode after) {
		SllNode afterNext=after.getNext();
		if (afterNext==null) after.setNext(new SllNode(payload));
		else if (payload >= afterNext.getPayload()) pushOrder(payload,afterNext);
		else {
			SllNode newNode = new SllNode(payload);
			// Insert new node in list between after and afternext
			after.setNext(newNode);
			newNode.setNext(afterNext);
		}
	}

	@Override
	public String toString() {
		if (head==null) return "empty";
		return toString(head);
	}
	
	public String toString(SllNode from) {
		assert(from!=null);
		SllNode next=from.getNext();
		if (next==null) return from.toString() + " -> null";
		return from.toString() + " -> " + toString(next);
	}

	private class SllNode {
		private int payload;
		private SllNode next;
		
		public SllNode(int payload) {
			this.payload=payload;
			this.next=null;
		}
	
		public int getPayload() { return payload; }
		
		public SllNode getNext() { return next; }
	
		public void setNext(SllNode next) { this.next = next; }
	
		@Override
		public String toString() {
			return "[" + payload +"]" ;
		}	
	
	}

}