import becker.util.Test;


public class ElementSLL

{   private int numItems;
    private ElementNode head;

    //post: creates an ElementSLL object with head "theHead"
    public ElementSLL(ElementNode theHead)
    {   this.head = theHead;
        numItems = 1;
    }

    //post: returns number of items in this SLL
    public int getNumItems()
    {   return numItems;
    }

    //post: returns the head in this SLL
    public ElementNode getHead()
    {   return this.head;
    }

    //pre:  column is not larger than the number of columns in the matrix
    //post: returns the value stored in the entry at "column"
    public int findValue(int column)
    {   ElementNode theNode = this.head;
        boolean nextNull = false;
        while(nextNull == false)
        {   if(theNode.getColumn() == column)
            {   return theNode.getValue();
            }
            else if(theNode.getNext() == null)
            {   nextNull = true;
            }
            else
            {   theNode = theNode.getNext();
            }
        }
        //could not find any value in the specified column, thus, it is zero
        return 0;
    }

    //pre:   addedNode not null
    //post:  If zero entry exists at the row and column specified by addedNode,
    //       adds a new ElementNode at that row and column.  If an ElementNode already
    //       exists there, sets that ElementNode's value to addedNode's value
    public void add(ElementNode addedNode)
    {   ElementNode tempNode = this.head;
        boolean foundPosition = false;

        //this only becomes true if addedNode should be placed before the existing head
        if(addedNode.getColumn() <= tempNode.getColumn())
        {   foundPosition = true;
        }

        while(tempNode.getColumn() < addedNode.getColumn() && tempNode.getNext() != null && foundPosition == false)
        {   if(tempNode.getColumn() > addedNode.getColumn())
            {   foundPosition = true;
            }
            else
            {  tempNode = tempNode.getNext();
            }
        }

        if(tempNode.getColumn() == addedNode.getColumn())
        {   tempNode.setValue(addedNode.getValue());
        }
        else if(foundPosition == true)
        {   if(tempNode.equals(head))
            {   addedNode.setNext(tempNode);
                this.head = addedNode;
            }
            else
            {   addedNode.setNext(tempNode.getNext());
                tempNode.setNext(addedNode);
            }
            numItems++;
        }
        else
        {   tempNode.setNext(addedNode);
            numItems++;
        }

    }

    //pre:  column is not larger than the number of columns in the matrix
    //post:  if an ElementNode exists at the specified column, removes the reference to that
    //      ElementNode, in effect making it a zero entry.  If no ElementNode exists at column,
    //      this method does nothing.
    public void remove(int column)
    {   ElementNode tempNode = this.head;
        boolean foundPosition = false;

        //only goes through here if you want to remove the head
        if(tempNode.getColumn() == column)
        {   this.head = this.head.getNext();
            numItems--;
            return;
        }

        while(tempNode.getNext() != null && foundPosition == false)
        {   if(tempNode.getNext().getColumn() == column)
            {   foundPosition = true;
            }
            else
            {   tempNode = tempNode.getNext();
            }
        }
        if(foundPosition == true)
        {   tempNode.setNext(tempNode.getNext().getNext());
            numItems--;
        }
        //if boolean remained false, means that no ElementNode existed at column, so we do nothing
    }


   public static void main(String[] args)
   {
       ElementNode head = new ElementNode(1,2,5);
       ElementNode e1 = new ElementNode(1,4,10);
       ElementNode e2 = new ElementNode(1,5,8);
       ElementNode newHead = new ElementNode(1,1,216);
       ElementSLL s1 = new ElementSLL(head);

       Test.ckEquals("Testing getNumItems", 1, s1.getNumItems());
       Test.ckEquals("Testing getHead", head.getColumn(), s1.getHead().getColumn());

       Test.ckEquals("Testing findValue", 5, s1.findValue(2));
       Test.ckEquals("Testing findValue - column not there", 0, s1.findValue(4));

       s1.add(e2);
       Test.ckEquals("Testing add", 5, s1.getHead().getNext().getColumn());

       s1.add(e1);
       Test.ckEquals("Testing add", 4, s1.getHead().getNext().getNext().getColumn());
       Test.ckEquals("Testing add", 10, s1.findValue(4));

       Test.ckIsNull("Testing add next is null", s1.getHead().getNext().getNext().getNext());

       Test.ckEquals("Testing findValue - column not there", 0, s1.findValue(3));

       Test.ckEquals("Testing remove", 10, s1.findValue(4));
       s1.remove(4);
       Test.ckEquals("Testing remove", 0, s1.findValue(4));
       Test.ckEquals("Testing remove - now next", 8, s1.getHead().getNext().getValue());

       s1.add(newHead);
       Test.ckEquals("Testing add - adding new head", 216, s1.getHead().getValue());

       s1.remove(1);
       Test.ckEquals("Testing remove - removed head", 5, s1.getHead().getValue());



       


   }

}

