package CipherCracker;

import it.unimi.dsi.fastutil.ints.IntArrayList;
import it.unimi.dsi.fastutil.ints.IntList;

import java.util.ArrayList;

public class PrimaryDecryptor {
    private static final int ALPHABET_SIZE = 26;

    private static String executeConversion(IntList currentKey, ArrayList<Integer> cipherWord, int keyOffset) {
        int wordLength = cipherWord.size();
        int[] decryptedBuffer = new int[wordLength];

        for (int i = 0; i < wordLength; i++) {
            int cipherValue = cipherWord.get(i);

            // Fetch the key value using the rolling offset
            int keyValue = currentKey.getInt((i + keyOffset) % currentKey.size());

            // Uses Math.floorMod to correctly handle negative results
            int decryptedValue = Math.floorMod(cipherValue - keyValue, ALPHABET_SIZE);
            decryptedBuffer[i] = decryptedValue;
        }

        IntList results = new IntArrayList(decryptedBuffer);

        return ConverterHelpers.reversePrimaryIdentifierConverter(results);
    }

    public static String decrypt(String cipherText, String key) {
        // Converts the key string into an integer list
        ArrayList<Integer> encodedKeyList = ConverterHelpers.primaryIdentifierConverter(key);
        IntList encodedKey = new IntArrayList(encodedKeyList);

        StringBuilder decryptedText = new StringBuilder();
        int keyOffset = 0;

        // Splits the cipherText into individual words
        String[] cipherWords = cipherText.split("\\s+");

        // Process each word while maintaining the key offset
        for (int i = 0; i < cipherWords.length; i++) {
            String word = cipherWords[i];

            // Convert the current cipher word into a list of integers
            ArrayList<Integer> cipherWordInts = ConverterHelpers.primaryIdentifierConverter(word);

            // Decrypt the current word
            String decryptedWord = executeConversion(encodedKey, cipherWordInts, keyOffset);
            decryptedText.append(decryptedWord);

            // Update the offset so the key sequence continues correctly for the next word
            keyOffset = (keyOffset + cipherWordInts.size()) % encodedKey.size();

            // Re-add spaces between words (except after the last word)
            if (i < cipherWords.length - 1) {
                decryptedText.append(" ");
            }
        }

        // 4. Output the fully decrypted string
        return decryptedText.toString();
    }
}