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

#define MAX_STR 1000
#define NUM_LETRAS 26

int main() {

    int i, j;

    char alfabeto[] = "abcdefghijklmnopqrstuvwxyz";
    char ordem[] = "aeosrdnitmulcvpgqbfhjxzkyw";
    char trocas[] = "jgmfri";
    char chave[NUM_LETRAS + 1]; // + 1 por causa do terminador da string.
    int frequencias[NUM_LETRAS];
    int frequencias2[NUM_LETRAS];
    char codificado[MAX_STR];
    char decodificado[MAX_STR];

    // Passo 1:
    // Limpa o vetor "frequencias".
    for (i = 0; i < NUM_LETRAS; i++) {
        frequencias[i] = 0;
    }

    // Passo 2:
    // Lê a string codificada do usuário.
    printf("Digite o texto criptografado: ");
    fgets(codificado, MAX_STR, stdin);

    // Passo 3:
    // Percorre a string "codificado" e conta quantas vezes cada letra aparece,
    // guardando a contagem no vetor "frequencias".
    for (i = 0; codificado[i]; i++) {
        if (codificado[i] >= 'a' && codificado[i] <= 'z') { // Se for letra minúscula.
            frequencias[codificado[i] - 'a']++;
        } else if (codificado[i] >= 'A' && codificado[i] <= 'Z') { // Se for letra maiúscula.
            frequencias[codificado[i] - 'A']++;
        }
        // Poderia ter um else para os casos onde não é nenhum dos dois,
        // mas quando isso acontece, não precisamos fazer nada.
    }

    // Passo 4 (opcional):
    // Mostra o vetor "frequencias".
    // Aproveita para copiar "frequencias" para "frequencias2".
    printf("\n\nTabela de frequências:");
    for (i = 0; i < NUM_LETRAS; i++) {
        printf(" %c=%d", i + 'a', frequencias[i]);
        frequencias2[i] = frequencias[i];
    }
    printf("\n");

    // Passo 5:
    // Percorre a tabela "frequencias" para montar a "chave", utilizando a ordem das letras
    // dada pelo vetor "ordem". Entretanto, o vetor "frequencias" acaba sendo destruído
    // por esse processo, e é por isso que temos uma cópia em "frequencias2".
    for (i = 0; i < NUM_LETRAS; i++) {
        int maior = -1;
        int maior_indice = 0;
        for (j = 0; j < NUM_LETRAS; j++) {
            if (frequencias[j] >= maior) {
                maior = frequencias[j];
                maior_indice = j;
            }
        }
        chave[maior_indice] = ordem[i];
        frequencias[maior_indice] = -1;
    }
    chave[NUM_LETRAS] = 0;

    // Passo 6 (opcional):
    // Percorre a tabela "frequencias2" para procurar por letras que ocorram um mesmo
    // número de vezes (que não seja zero) e mostrar isso ao usuário.
    // Entretanto, "frequencias2" acaba sendo destruído nesse processo.
    for (i = 0; i < NUM_LETRAS; i++) {
        if (frequencias2[i] == 0) continue;
        int p = 0;
        for (j = i + 1; j < NUM_LETRAS; j++) {
            if (frequencias2[j] != frequencias2[i]) continue;
            if (p == 0) {
                printf("Frequências iguais [%d]: %c", frequencias2[i], i + 'a');
                p = 1;
            }
            printf("%c", (j + 'a'));
            frequencias2[j] = 0;
        }
        frequencias2[i] = 0;
        if (p != 0) printf("\n");
    }

    // Passo 7 (opcional):
    // Troca algumas letras da "chave" a fim de ajeitar manualmente os casos que estiverem errados.
    // As letras das posições pares são permutadas com as das posições ímpares de "trocas".
    for (i = 0; trocas[i]; i += 2) {
        char temp = chave[trocas[i] - 'a'];
        chave[trocas[i] - 'a'] = chave[trocas[i + 1] - 'a'];
        chave[trocas[i + 1] - 'a'] = temp;
    }

    // Passo 8 (opcional):
    // Mostra a chave.
    printf("\nA chave é:\n%s\n%s\n", alfabeto, chave);

    // Passo 9:
    // Tendo o vetor "chave" montado, usa ele para formar a string "decodificado"
    // a partir de "codificado".
    for (i = 0; codificado[i]; i++) {
        if (codificado[i] >= 'a' && codificado[i] <= 'z') { // Letras minúsculas.
            decodificado[i] = chave[codificado[i] - 'a'];
        } else if (codificado[i] >= 'A' && codificado[i] <= 'Z') { // Letras maiúsculas.
            decodificado[i] = chave[codificado[i] - 'A'] - 'a' + 'A';
        } else { // Copia qualquer outra coisa diretamente.
            decodificado[i] = codificado[i];
        }
    }
    decodificado[i] = codificado[i]; // Copia o terminador nulo.

    // Passo 10:
    // Mostra o texto "decodificado".
    printf("\nO texto descriptografado é:\n%s\n", decodificado);  
}