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

typedef struct Node {
    char data;
    struct Node * next;
} node;

node * initLinkedList() {
    /* initalize the linked list (has head node) */
    node * p = (node *)malloc(sizeof(node));
    node * temp = p;

    int i;
    for (i = 0; i < 4; i++) {
        node * n = (node *)malloc(sizeof(node));
        n->data = i;
        n->next = NULL;

        temp->next = n;
        temp = temp->next;
    }

    return p;
}

node * insertElem(node * p, int elem, int index) {
    node * temp = p; 

    int i;
    for (i = 0; i < index; i++) {
        if (temp == NULL) {
            printf("Illegal Index");
            return p;
        }
        temp = temp->next;
    }

    node * newNode = (node *)malloc(sizeof(node));
    newNode->data = elem;

    newNode->next = temp->next;
    temp->next = newNode;

    return p;
}

node * deleteElem(node * p, int index) {
    node * temp = p;

    int i;
    for (i = 0; i < index; i++) {
        temp = temp->next;
    }

    node * del = temp->next;
    temp->next = temp->next->next;

    free(del);

    return p;
}

int searchElem(node * p, int elem) {
    node * temp = p;

    int i = 0;
    while (temp->next) {
        temp = temp->next;
        if (temp->data == elem) {
            return i; // return the index of the element
        }
        i++;
    }

    return -1; // if not found
}

node * updateElem(node * p, int index, int newElem) {
    node * temp = p;

    int i;
    for (i = 0; i <= index; i++) {
        temp = temp->next;
    }

    temp->data = newElem;

    return p;
}

void display(node * p) {
    /* display the linked list (has head node) */
    node * temp = p;
    while (temp->next) {
        temp = temp->next;
        printf("%d ", temp->data);
    }
    printf("\n");
}

int main(void) {
    printf("Linked List: ");
    node * p = initLinkedList();
    display(p);

    p = insertElem(p, 10, 1);
    p = insertElem(p, 20, 1);
    printf("After insertion: ");
    display(p);

    p = deleteElem(p, 1);
    p = deleteElem(p, 1);
    printf("After deletion: ");
    display(p);

    printf("Index of \"2\": %d\n", searchElem(p, 2));

    p = updateElem(p, 1, 100);
    printf("After update: ");
    display(p);

    return 0;
}