#include <stdlib.h>
#include <assert.h>
#include <stdio.h>

#include "../mecha/mecha.h"

#include "iterator.h"

#include "list_iterator.h"

struct s_ListIterator
{
    IIterator interface;

    lstTlist *list;
    lstTlist_elem *cur_elem;

    int list_size;
};


static IteratorStatus list_iterator_next (IIterator *inst);
static void * list_iterator_value (IIterator *inst);

ListIterator *
list_iterator_new (lstTlist *list)
{
    ListIterator *instance = (ListIterator *) malloc (sizeof (ListIterator));

    instance->interface.next = list_iterator_next;
    instance->interface.get_value = list_iterator_value;
    instance->interface.destroy = list_iterator_destroy;

    instance->list = list;
    instance->cur_elem = NULL;

    instance->list_size = lstFlist_size (list);

    return (instance);
}

void
list_iterator_destroy (IIterator *inst)
{
    ListIterator *instance = (ListIterator *) inst;

    free (instance);
}

static IteratorStatus
list_iterator_next (IIterator *inst)
{
    ListIterator *instance = (ListIterator *) inst;

    if (lstFlist_size (instance->list) != instance->list_size)
    {
        return (IteratorOutOfSync);
    }

    if (instance->cur_elem == NULL)
    {
        instance->cur_elem = lstFlist_head (instance->list);
    }
    else
    {
        instance->cur_elem = lstFlist_next (instance->cur_elem);
    }

    if (instance->cur_elem != NULL)
    {
        return (IteratorSuccess);
    }
    else
    {
        return (IteratorEnd);
    }
}

static void *
list_iterator_value (IIterator *inst)
{
    ListIterator *instance = (ListIterator *) inst;

    assert (instance->cur_elem != NULL);

    return (lstFlist_data (instance->cur_elem));
}
