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

typedef struct no_teste {
    int valor;
    struct no_teste *ant;
    struct no_teste *prox;
} no_teste;

void inserir(no_teste** lista, int valor){
    no_teste* novo = malloc(sizeof(no_teste));
    novo->valor = valor;
    novo->ant = NULL;

    if (*lista == NULL){
        *lista = novo;
        (*lista)->prox = NULL;
    }
    else {
        novo->prox = *lista;
        (*lista)->ant = novo;
        *lista = novo;
    }
}

no_teste* obter_no(no_teste* lista, int valor){
    no_teste* corrente = lista;

    while (corrente != NULL){
        if (corrente->valor == valor) {
            return corrente;
        }
        corrente = corrente->prox;
    }

    return NULL;
}

void mostrar(no_teste* lista){
    printf("\nLista: ");
    no_teste* corrente = lista;

    while (corrente != NULL){
        printf("%d -> ", corrente->valor);
        corrente = corrente->prox;
    }
    printf("NULL");
}

void mostrarReverso(no_teste* lista){
    printf("\nLista invertida: ");
    no_teste* corrente = lista;

    while (corrente->prox != NULL){
        corrente = corrente->prox;
    }

    while (corrente != NULL){
        printf("%d -> ", corrente->valor);
        corrente = corrente->ant;
    }

    printf("NULL");
}

void swap(no_teste** lista, no_teste* A, no_teste* B) {
    if (A->ant != NULL){
        A->ant->prox = B;
    }
    else {
        *lista = B;
    }

    if (B->prox != NULL){
        B->prox->ant = A;
    }

    A->prox = B->prox;
    B->ant = A->ant;
    B->prox = A;
    A->ant = B;
}

int main(){
    no_teste* lista = NULL;

    inserir(&lista, 10);
    inserir(&lista, 15);
    inserir(&lista, 2);
    inserir(&lista, 9);
    inserir(&lista, 4);

    printf("Lista inicial\n");
    mostrar(lista);
    mostrarReverso(lista);

    printf("\n\nTroca de 9 e 2:\n");
	
    no_teste* no9 = obter_no(lista, 9);
    no_teste* no2 = obter_no(lista, 2);
    swap(&lista,no9, no2);

    mostrar(lista);
    mostrarReverso(lista);
    
    printf("\n\nTroca de 15 e 10:\n");

    no_teste* no15 = obter_no(lista, 15);
    no_teste* no10 = obter_no(lista, 10);
    swap(&lista,no15, no10);

    mostrar(lista);
    mostrarReverso(lista);
    
    printf("\n\nTroca de 4 e 2:\n");

    no_teste* no4 = obter_no(lista, 4);
    swap(&lista,no4, no2);

    mostrar(lista);
    mostrarReverso(lista);
    return 0;
}
