
public class LinkedList<T> {

	private Node<T> head=null;
	private int size=0;

	public void print(){
		Node<T> pos = head;
		if(pos==null){
			System.out.println("NO Nodes !!");
		}
		else{
			while(pos != null){
				System.out.print(pos.toString()+",");
				pos=pos.getNext();
			}
			System.out.println();
		}
		
	}
	public void printReverse(){
		Node<T> pos=head;
		for(int i=0;i<size-1;++i)
			pos=pos.getNext();

		while(pos!=null){
			System.out.print(pos.toString()+",");
			pos=pos.getPrev();
		}
		System.out.println();
	}
	public boolean add(T data,int index){
		Node<T> newNode = new Node<>(data);
		Node<T> pos=head;
		if(head==null){
			head=newNode;
			++size;
			return true;
		}
		if(index==0){
			newNode.setNext(head);
			head.setPrev(newNode);
			head=newNode;
			++size;
			return true;

		}
		if(index < 0 || index > size )
			return false;
		else{
			for(int i=0;i<index-1;++i)
				pos=pos.getNext();

			Node<T> temp = pos.getNext();

			newNode.setNext(temp);
			if(temp!=null)	
				temp.setPrev(newNode);
			pos.setNext(newNode);
			newNode.setPrev(pos);


			++size;
			return true;
		}
	}
	public boolean addInsertion(T data){
		Node<T> newNode = new Node<>(data);
		Node<T> pos=head;
		if(head==null){
			head=newNode;
			++size;
			return true;
		}
		if(pos.compare(newNode)>0){
			newNode.setNext(head);
			if(newNode.getNext() != null)
				newNode.getNext().setPrev(newNode);
			head=newNode;
			++size;
			return true;
		}
		while(pos.getNext()!=null && pos.getNext().compare(newNode)<0)
			pos=pos.getNext();
		
		newNode.setNext(pos.getNext());
		if(pos.getNext()!=null)
			pos.getNext().setPrev(newNode);
		newNode.setPrev(pos);
		pos.setNext(newNode);
		
		++size;
		return true;
		
		
	}

	public boolean add(T data){
		Node<T> newNode = new Node<>(data);
		Node<T> pos = head;

		if(head==null){
			head=newNode;
			++size;
			return true;
		}

		while(pos.getNext()!=null)
			pos=pos.getNext();

		newNode.setNext(pos.getNext());
		pos.setNext(newNode);
		newNode.setPrev(pos);
		++size;
		return true;

	}

	public boolean removeIndex(int index){
		if(index < 0 || index > size || this.isEmpty())
			return false;

		if(index==0){
			head = head.getNext();
			if(head!=null)
				head.setPrev(null);
			--size;
			return true;	
		}
		Node<T> pos= head;
		for(int i=0;i<index-1;++i){
			pos=pos.getNext();
		}
		pos.setNext(pos.getNext().getNext());
		if(pos.getNext()!=null)
			pos.getNext().setPrev(pos);

		--size;
		return true;

	}

	public boolean removeObject(T data){
		if(this.isEmpty())
			return false;
		Node<T> pos= head;

		if(pos.equalTo(data)){
			head = head.getNext();
			if(head!=null)
				head.setPrev(null);
			--size;
			return true;	
		}
		while(pos.getNext()!=null){

			if(pos.getNext().equalTo(data)){
				pos.setNext(pos.getNext().getNext());
				if(pos.getNext()!=null)
					pos.getNext().setPrev(pos);

				--size;
				return true;
			}
			pos=pos.getNext();
		}
		return false;


	}

	public T getData(int index){
		Node<T> pos = head;

		if(index < 0 || index > size || this.isEmpty())
			return null;


		for(int i =0;i<index;++i){
			pos=pos.getNext();
		}
		return pos.getData();

	}

	public Node<T> getHead() {
		return head;
	}
	public int getSize() {
		return size;
	}

	public boolean isEmpty(){
		if(head==null)
			return true;
		else
			return false;
	}
}
