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

struct Node {
    char *data;
    struct Node *prev;
    struct Node *next;
};

struct Node* createNode(const char *data) {
    struct Node *newNode = (struct Node*)malloc(sizeof(struct Node));
    if (!newNode) return NULL;

    newNode->data = (char*)malloc(10 * sizeof(char));
    strncpy(newNode->data, data, 9);
    newNode->data[9] = '\0';

    newNode->prev = NULL;
    newNode->next = NULL;

    return newNode;
}

void insertAfter(struct Node *node, const char *data) {
    if (!node) return;

    struct Node *newNode = createNode(data);

    newNode->next = node->next;
    newNode->prev = node;

    if (node->next)
        node->next->prev = newNode;

    node->next = newNode;
}

void insertBefore(struct Node **head, struct Node *node, const char *data) {
    if (!node || !head) return;

    struct Node *newNode = createNode(data);

    newNode->next = node;
    newNode->prev = node->prev;

    if (node->prev)
        node->prev->next = newNode;
    else
        *head = newNode;

    node->prev = newNode;
}

void deleteNode(struct Node **head, struct Node *node) {
    if (!node || !head || !*head) return;

    if (node->prev)
        node->prev->next = node->next;
    else
        *head = node->next;

    if (node->next)
        node->next->prev = node->prev;

    free(node->data);
    free(node);
}

void printList(struct Node *head) {
    printf("List: ");
    while (head) {
        printf("%s <-> ", head->data);
        head = head->next;
    }
    printf("NULL\n");
}

void freeList(struct Node *head) {
    struct Node *tmp;
    while (head) {
        tmp = head;
        head = head->next;
        free(tmp->data);
        free(tmp);
    }
}

int main() {

    printf("==== POPULATE LIST ====\n");

    struct Node *head = createNode("A");
    struct Node *b = createNode("B");
    struct Node *c = createNode("C");

    head->next = b;
    b->prev = head;

    b->next = c;
    c->prev = b;

    printList(head);

    printf("\n==== INSERT AFTER B ====\n");
    insertAfter(b, "X");
    printList(head);

    printf("\n==== INSERT BEFORE B ====\n");
    insertBefore(&head, b, "Y");
    printList(head);

    printf("\n==== DELETE NODE B ====\n");
    deleteNode(&head, b);
    printList(head);

    printf("\n==== INSERT AT HEAD (before A) ====\n");
    insertBefore(&head, head, "HEAD");
    printList(head);

    printf("\n==== INSERT AFTER TAIL ====\n");
    struct Node *tail = head;
    while (tail->next) tail = tail->next;
    insertAfter(tail, "TAIL+1");
    printList(head);

    printf("\n==== CLEANUP MEMORY ====\n");
    freeList(head);

    return 0;
}