#include "ilist.h"


IList* ilist_new() {

    IList* l=NULL;
    IElement* e=NULL;

    l=(IList*)malloc(sizeof(IList));
    assert(l!=NULL);

    e=(IElement*)malloc(sizeof(IElement));
    assert(e!=NULL);

    e->next=NULL;
    e->prev=NULL;
    e->val=-1;
    l->length=0;
    l->head=e;
    l->tail=e;
    l->iter=NULL;
    l->lastIterIndex=-1;

    return l;
    
}

IList* ilist_new_from_mask(unsigned char* mask,int count,unsigned char positiveVal) {

    IList* l=NULL;
    int i=0;
    assert(mask!=NULL && count>=0);

    l=ilist_new();
    for(i=0;i<count;i++) {
        if (mask[i]==positiveVal) ilist_append(l,i);
    }
    
    return l;
}

IList* ilist_new_sequence(int count) {

    IList* l=NULL;
    int i=0;

    assert(count>0);

    l=ilist_new();
    for(i=0;i<count;i++) ilist_append(l,i);

    return l;

}

void ilist_make_mask(IList* l,unsigned char* maskPtr,int length,unsigned char positiveVal) {

    int i=0;
    assert(l!=NULL && maskPtr!=NULL);
    
    memset(maskPtr,!positiveVal,length);
    
    ilist_start_iteration(l);
    while(ilist_iterate(l,&i)) {
        maskPtr[i]=positiveVal;
    }

}

void ilist_delete(IList *l) {

    IElement* current=NULL;
    IElement* next=NULL;

    assert(l!=NULL);

    current=l->head;
    if (l->tail==current) {
        free(l->head);
        free(l);
        return;
    }

    while(current!=NULL) {
        next=current->next;
        free(current);
        current=next;
    }

    free(l);
}


void ilist_remove(IList *l,int index) {

    IElement* current;
    IElement* prev;
    int counter=-1;

    assert(l!=NULL);

    current=l->head;

    while(current->next!=NULL) {
        counter++;
        prev=current;
        current=current->next;
        if (counter==index) {
            prev->next=current->next;
            if (prev->next==NULL) l->tail=prev; else prev->next->prev=prev;
            free(current);
            l->length--;
            return;
        }
        
    }
    assert(0);
    
}
int  ilist_get(IList *l ,int index) {

    IElement* current;
    int counter=-1;

    assert(l!=NULL);

    current=l->head;

    while(current->next!=NULL) {
        counter++;
        current=current->next;
        if (counter==index) {
            return current->val;
        }

    }

    assert(0);
    return 0;
}

void ilist_append(IList* l,int value) {

    IElement* current=NULL;

    assert(l!=NULL);

    current=(IElement*)malloc(sizeof(IElement));
    current->next=NULL;
    current->val=value;
    current->prev=l->tail;

    l->tail->next=current;
    l->tail=current;

    l->length++;
    
}

IList* ilist_clone(IList* l) {
    IList* nl=NULL;
    int i=0;
    
    assert(l!=NULL);
    nl=ilist_new();

    for(i=0;i<l->length;i++) ilist_append(nl,ilist_get(l,i));
    return nl;
}

void ilist_start_iteration(IList* l) {

    assert(l!=NULL);

    l->iter=l->head->next;
    l->lastIterIndex=-1;
}

void ilist_start_deteration(IList* l) {
    assert(l!=NULL);
    l->iter=l->tail;
    l->lastIterIndex=l->length;
}

int ilist_deterate(IList* l,int* retVal) {

    if(l->iter==l->head) return 0;
    *retVal=l->iter->val;
    l->iter=l->iter->prev;
    l->lastIterIndex--;
    return 1;
}

int ilist_iterate(IList* l,int* retVal) {

    assert(l!=NULL);

    if (l->iter==NULL) return 0;

    *retVal=l->iter->val;
    l->iter=l->iter->next;
    l->lastIterIndex++;
    return 1;

}

void ilist_print(IList* l) {

    int i=0;
    assert(l!=NULL);

    printf("ILIST:");
    for(i=0;i<l->length;i++) {
        printf("%d,",ilist_get(l,i));
    }
    printf("\n");

}

