public class CircularLinkedList<E> {
	
	public int _size;
	public ListNode<E> _head;
	public ListNode<E> _tail;
	
	public void addFirst(E element) {
		_size++;
		_head = new ListNode<E>(element, _head);
		if (_tail == null)
			_tail = _head;
		_tail.setNext(_head);
	}
	
	public String toString() {
		StringBuilder buffer = new StringBuilder();
		buffer.append("[");
		if (_head != null) {
			ListNode<E> curr = _head;
			while (curr != _tail) {
				buffer.append(curr.getElement() + ", ");
				curr = curr.getNext();
			}
			buffer.append(_tail.getElement());
		}
		buffer.append("]");
		return buffer.toString();
	}
	
	public void swap(int index) {
		if (_size < 2)
			return; // if 0 or 1 nodes, don't bother
		if (_size == 2) {
			ListNode<E> newTail = _head;
			_head = _tail;
			_tail = newTail;
			return;
		} // if 2 nodes, only need to swap head and tail references
		
		// At this point, the list has >2 nodes
		index %= _size; // ensure that index < size of list first
		
		// get the 3 desired nodes
		ListNode <E> prev = _tail;
		for (int loopIdx = 0; loopIdx < index; loopIdx++)
			prev = prev.getNext();
		ListNode<E> curr = prev.getNext(); // curr now at indexed node
		ListNode<E> succ = curr.getNext();
		
		// swap the 2 nodes: Note the order! 
		curr.setNext(succ.getNext());
		succ.setNext(curr);
		prev.setNext(succ);
		
		if (index == 0) {
			_head = succ; // head incorrect
		} else if (index == _size- 2) {
			_tail = curr; // swap(tail-1), tail incorrect
		} else if (index == _size - 1) {
			_head = curr; // swap(tail), both head & tail swapped
			_tail = succ;
		}
	}
	
	public static void main(String[] args) {
		CircularLinkedList<Character> list13 = new CircularLinkedList<Character>();
		for (int offset = 12; offset >= 0; offset--) // 13 chars
			list13.addFirst((char)('a' + offset));
		System.out.println(list13.toString());
		list13.swap(15);
		System.out.println(list13.toString());
		
		CircularLinkedList<Character> list3 = new CircularLinkedList<Character>();
		for (int offset = 2; offset >= 0; offset--) // 3 chars
			list3.addFirst((char)('a' + offset));
		System.out.println(list3.toString());
		list3.swap(15);
		System.out.println(list3.toString());
		
		CircularLinkedList<Character> list2 = new CircularLinkedList<Character>();
		for (int offset = 1; offset >= 0; offset--) // 2 chars
			list2.addFirst((char)('a' + offset));
		System.out.println(list2.toString());
		list2.swap(3);
		System.out.println(list2.toString());
		
		CircularLinkedList<Character> list1 = new CircularLinkedList<Character>();
		list1.addFirst('a');
		System.out.println(list1.toString());
		list1.swap(3);
		System.out.println(list1.toString());
		
	}
}

