//SLL.class

//package sll_testeing;

public class SLL<E> {

    private SLLNode<E> first;

    // SLLNode<E>(momentalen_element, sleden_element_na_momentalniot)
    public SLL() {
        this.first = null;
    }
    
    public SLL(SLLNode<E> first) {
        this.first = first;
    }

    public SLLNode<E> getFirst() {
        return this.first;
    }

    public void insertFirst(E o) {
        SLLNode<E> ins = new SLLNode<E>(o, first);
        first = ins;
    }

    public void insertLast(E o) {
        if (first != null) {
            // Prviot clen od listata go dava na tmp
            SLLNode<E> tmp = first;
            // Ja izminuva listata i koga ke dojde do null
            // ciklusot pagja i tmp e ima poslednata vrednost
            while (tmp.succ != null) {
                tmp = tmp.succ;
            }
            // Kreira nov link/jazol so noviot link i za sleden
            // go stava null zatoa sto go stava na kraj od listata
            SLLNode<E> ins = new SLLNode<E>(o, null);
            //sledniot na tmp t.e krajot go stava novokreiraniot el
            tmp.succ = ins;
        } else { // ako listata e prazna
            insertFirst(o); // go stava na pocetokot
        }
    }

    public void insertAfter(E o, SLLNode<E> node) {
        if (node != null) {
            SLLNode<E> ins = new SLLNode<E>(o, node.succ);
            node.succ = ins;
        }
    }

    public void insertBefore(E o, SLLNode<E> before) {

        if (first != null) {
            SLLNode<E> tmp = first;
            if (first == before) {
                this.insertFirst(o);
                return;
            }
            while (tmp.succ != before) {
                tmp = tmp.succ;
            }

            if (tmp.succ == before) {
                SLLNode<E> ins = new SLLNode<E>(o, before);
                tmp.succ = ins;
            } else {
                System.out.println("Ne moze da se otpecati\n");
            }
        } else {
            System.out.println("Listata e prazna!");
        }
    }

    public void deleteFirst() {

        if (first != null) {
            first = first.succ;
        } else {
            System.out.println("Listata e prazna!");
        }
    }

    public void delete(E node) {
        if (first != null) {
            SLLNode<E> tmp = first;

            if (first == node) {
                first = null;
            }

            while (tmp.succ != node && tmp.succ.succ != null) {
                tmp.succ = tmp.succ.succ;
            }

            if (tmp.succ == node) {
                tmp.succ = tmp.succ.succ;
            }
        } else {
            System.out.println("Listata e prazna!");
        }
    }

    public int length() {
        int counter = 0;
        if (first != null) {
            counter++;
            SLLNode<E> tmp = first;
            while (tmp.succ != null) {
                tmp = tmp.succ;
                counter++;
            }
        }
        return counter;
    }

    public void merge(SLL<E> to_be_merged) {
        if (first != null) {
            SLLNode<E> tmp = first;
            while (tmp.succ != null) {
                tmp = tmp.succ;
            }
            //SLLNode<E> ins = new SLLNode<E>(to_be_merged.getFirst(), )
            tmp.succ = to_be_merged.getFirst();
        } else {
            first = to_be_merged.getFirst();
        }
    }

    public void mirror() {
        if(first != null)
        {
            SLLNode<E> tmp = first;
            SLLNode<E> newsucc = null;
            SLLNode<E> succ = null;
            
            while(tmp != null)
            {
                succ = tmp.succ;
                tmp.succ = newsucc;
                newsucc = tmp;
                tmp = succ;
            }
            first = newsucc;
        }
    }
    
    public void remove_duplicates()
    {
        if (first == null)
            return;
        SLLNode<E> tmp = first;
        while (tmp != null)
        {
            SLLNode<E> prevNode = tmp;
            SLLNode<E> currNode = tmp.succ;
            while (currNode != null)
            {
                //System.out.printf("Momentalen jazol vo vtoriot ciklus: %s\n", currNode.element.toString());
                if (tmp.element == currNode.element)
                {
                    //Prebrisuvanje ako e pronajden ist element!
                    //So sledniot na tmp. (pevNode.succ)
                    prevNode.succ = currNode.succ;
                } else {
                    prevNode = currNode; //updating prevNode in case of not a match
                }
                currNode = currNode.succ;
            }
            tmp = tmp.succ;
        }
        
    }
    

    @Override
    public String toString() {
        String ret = new String();
        if (first != null) {
            SLLNode<E> tmp = first;
            ret += tmp + "-->";
            while (tmp.succ != null) {

                tmp = tmp.succ;
                ret += tmp + "-->";
            }
        } else {
            System.out.println("Prazna lista");
            //System.exit(1);
        }

        return ret;

    }

}
