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

typedef int bool;
enum { false, true };

// elemento da lista
typedef struct estr {
    char letra;
    struct estr *prox;
} NO;

typedef struct {
    NO *inicio;
} LISTA;

void inicializarLista(LISTA *l) {
    l->inicio = NULL;
}

//início das funções de teste

void criarLista(LISTA *l, char plvr[]) {
    NO *ult = NULL;
    int i;

    for (i = 0; i < strlen(plvr); i++) {
        NO *novo = (NO *) malloc(sizeof(NO));
        novo->letra = plvr[i];
        novo->prox = NULL;
        if (ult) {
            ult->prox = novo;
        } else {
            l->inicio = novo;
        }
        ult = novo;
    }
}

void imprimirLista(LISTA *l) {
    NO *p = l->inicio;
    while(p) {
        printf("%c", p->letra);
        p = p->prox;
    }
}

LISTA* clonarLista(LISTA* l){
  LISTA* resp = malloc(sizeof(LISTA));

  NO *corrente = l->inicio;
  NO *anterior = NULL; //utilizar um nó anterior para ligar os vários elementos

  while(corrente){ //agora com corrente em vez de l
    NO *novo = (NO *) malloc(sizeof(NO));
    novo->letra = corrente->letra;
    novo->prox = NULL;

    if (anterior == NULL){ //se é o primeiro fica no inicio da nova lista
        resp->inicio = novo;
    }
    else { //se não é o primeiro liga o anterior a este pelo prox
        anterior->prox = corrente;
    }

    anterior = novo;
    corrente = corrente->prox;
  }

  return resp;
}



void inverter(LISTA* resp){

    NO* atual = resp->inicio;

    /*redefinir a lista para começar vazia, sendo que o ponteiro atual ainda
    aponta para os seus elementos*/
    resp->inicio = NULL;

    while (atual->prox != NULL){ //enquanto houver nós
        NO* corrente = atual; //guardar nó corrente
        atual = atual->prox; //avançar nó atual


        corrente->prox = resp->inicio; //fazer o prox do corrente ser o 1 da lista invertida
        resp->inicio = corrente; //o inicio passa a ser este ultimo nó
    }
}

//fim das funções de teste

void inverterNvs(NO* elemento, NO* anteriorAoElemento, NO* fim) {
    if (elemento != fim) {
        inverterNvs(elemento->prox, elemento, fim);
    }
    elemento->prox = anteriorAoElemento;
}


bool verificaSequencia(NO* dado) {
    if (dado->letra != 'a' && dado->letra != 'e' && dado->letra != 'i' && dado->letra != 'o' && dado->letra != 'u'){
        return true;
    }
    else{
        return false;
    }
}

void decodificar(LISTA* resp) {
    NO* pNv = NULL; // Primeira não-vogal encontrada.
    NO* ultNv = NULL; // Última não-vogal encontrada.

    NO* atual = resp->inicio; // Ponteiro para percorrer a lista.

    NO* anterior = NULL;

    /* Laço para percorrer toda lista. */
    while (atual != NULL) {


        /* Enquanto atual apontar para uma não-vogal. */
        if (verificaSequencia(atual)) {
            /* Salva o primeiro caso encontrado de não-vogal. */
            pNv = atual;


            /* Procura na lista o último caso de não-vogal. */
            while (atual->prox != NULL && verificaSequencia(atual->prox)) {
                atual = atual->prox;
            }

            /* Quando a próxima letra for uma vogal, então foi atingido o fim da sequência de não-vogais. */
            ultNv = atual;

            /* Se existir uma sequência de não-vogais, ou seja, pNv e ultNv não apontarem para o mesmo elemento, então a troca de posições deve ser efetuada. */
            if (pNv != ultNv) {
                /* Chama uma função recursiva para efetuar a troca de posições sem precisar criar uma nova lista. */

                NO* proximoOriginal = ultNv->prox;

                inverterNvs(pNv->prox, pNv, ultNv);

                pNv->prox = proximoOriginal;
                
                if (anterior == NULL){
                    resp->inicio = ultNv;
                }
                else {
                    anterior->prox = ultNv;
                }
                
                atual = pNv;
            }
        }

        /* Move para o próximo elemento. */
        anterior = atual;
        atual = atual->prox;
    }
}


int main() {
    LISTA l;
    inicializarLista(&l);
    //A partir de um vetor de char uma lista foi gerada para testes
    char palavra[] = "monstros legais"; //Resultado esperado: "mortsnol segais"
    criarLista(&l, palavra);

    LISTA* resp = clonarLista(&l); //obter o clonado
    //inverter(resp); //inverter o clonado
    //imprimirLista(resp); //imprimir o clonado

    decodificar(resp);
    imprimirLista(resp);



    return 0;
}
