package com.tiedup.remake.dialogue;

import java.util.Set;
import java.util.regex.Pattern;

/**
 * Detects and applies emotional context to gagged speech.
 */
public class EmotionalContext {

    /**
     * Types of emotional expression that affect speech transformation.
     */
    public enum EmotionType {
        NORMAL,
        SHOUTING,
        WHISPERING,
        QUESTIONING,
        PLEADING,
        DISTRESSED,
        LAUGHING,
        CRYING,
    }

    // Pattern for extended vowels (nooooo, heeelp, pleeease)
    private static final Pattern EXTENDED_VOWELS = Pattern.compile(
        "([aeiou])\\1{2,}",
        Pattern.CASE_INSENSITIVE
    );

    // Pattern for laughing (haha, hehe, lol)
    private static final Pattern LAUGHING_PATTERN = Pattern.compile(
        "(ha){2,}|(he){2,}|(hi){2,}|lol|lmao|xd",
        Pattern.CASE_INSENSITIVE
    );

    // Pattern for crying indicators
    private static final Pattern CRYING_PATTERN = Pattern.compile(
        "\\*(?:sob|cry|sniff|whimper)s?\\*|;-?;|T[-_]T|:'+\\(",
        Pattern.CASE_INSENSITIVE
    );

    // Pleading keywords
    private static final Set<String> PLEADING_WORDS = Set.of(
        "please",
        "help",
        "stop",
        "no",
        "don't",
        "dont",
        "wait",
        "s'il vous plait",
        "svp",
        "aide",
        "aidez",
        "arrete",
        "arreter",
        "non",
        "mercy",
        "spare",
        "let me go",
        "release"
    );

    // Whispering indicators
    private static final Set<String> WHISPERING_INDICATORS = Set.of(
        "*whisper*",
        "*whispers*",
        "*quietly*",
        "*softly*",
        "(whisper)",
        "(quietly)"
    );

    /**
     * Detect the emotional context of a message or word.
     *
     * @param text The text to analyze
     * @return The detected emotion type
     */
    public static EmotionType detectEmotion(String text) {
        if (text == null || text.isEmpty()) {
            return EmotionType.NORMAL;
        }

        String lower = text.toLowerCase();

        // Check for explicit emotional markers first
        if (CRYING_PATTERN.matcher(text).find()) {
            return EmotionType.CRYING;
        }

        if (LAUGHING_PATTERN.matcher(text).find()) {
            return EmotionType.LAUGHING;
        }

        // Check for whispering indicators
        for (String indicator : WHISPERING_INDICATORS) {
            if (lower.contains(indicator)) {
                return EmotionType.WHISPERING;
            }
        }

        // Check for shouting (ALL CAPS with 3+ letters, or multiple !)
        String letters = text.replaceAll("[^a-zA-Z]", "");
        if (letters.length() >= 3 && letters.equals(letters.toUpperCase())) {
            return EmotionType.SHOUTING;
        }
        // Require at least 2 exclamation marks for shouting
        if (text.contains("!!") || text.contains("!?") || text.contains("?!")) {
            return EmotionType.SHOUTING;
        }

        // Check for questioning
        if (text.endsWith("?") || text.endsWith("??")) {
            return EmotionType.QUESTIONING;
        }

        // Check for distress (extended vowels: nooooo, heeelp)
        if (EXTENDED_VOWELS.matcher(text).find()) {
            return EmotionType.DISTRESSED;
        }

        // Check for pleading keywords
        for (String word : PLEADING_WORDS) {
            if (lower.contains(word)) {
                return EmotionType.PLEADING;
            }
        }

        return EmotionType.NORMAL;
    }

    /**
     * Apply emotional modifiers to a muffled message.
     *
     * @param muffled  The muffled text
     * @param emotion  The detected emotion type
     * @return Modified text with emotional expression
     */
    public static String applyEmotionalModifiers(
        String muffled,
        EmotionType emotion
    ) {
        if (muffled == null || muffled.isEmpty()) {
            return muffled;
        }

        switch (emotion) {
            case SHOUTING:
                // Convert to uppercase and emphasize
                return (
                    muffled.toUpperCase() + (muffled.endsWith("!") ? "!" : "!!")
                );
            case WHISPERING:
                // Softer, shorter sounds
                return "*" + muffled.toLowerCase() + "*";
            case QUESTIONING:
                // Rising intonation
                String question = muffled.endsWith("?")
                    ? muffled
                    : muffled + "?";
                return question.replace("mm", "mn").replace("nn", "nh");
            case PLEADING:
                // Add whimpering
                return muffled + "-mm..";
            case DISTRESSED:
                // Extend the dominant sound
                return extendDominantSound(muffled);
            case LAUGHING:
                // Muffled laughter
                return muffled.replace("mm", "hm").replace("nn", "hn") + "-hm";
            case CRYING:
                // Add sobbing sounds
                return "*hic* " + muffled + " *mm*";
            case NORMAL:
            default:
                return muffled;
        }
    }

    /**
     * Extend the dominant/repeated sound in a muffled word for distress effect.
     */
    private static String extendDominantSound(String text) {
        if (text == null || text.length() < 2) {
            return text;
        }

        StringBuilder result = new StringBuilder();
        char prev = 0;
        int repeatCount = 0;

        for (int i = 0; i < text.length(); i++) {
            char c = text.charAt(i);

            if (c == prev && Character.isLetter(c)) {
                repeatCount++;
                // Extend repeated sounds
                if (repeatCount <= 3) {
                    result.append(c);
                }
            } else {
                result.append(c);
                repeatCount = 1;
            }
            prev = c;
        }

        // If no extension happened, extend the last vowel-like sound
        String str = result.toString();
        if (str.equals(text)) {
            // Find last 'm' or 'n' or vowel and extend it
            int lastExtendable = -1;
            for (int i = str.length() - 1; i >= 0; i--) {
                char c = Character.toLowerCase(str.charAt(i));
                if (c == 'm' || c == 'n' || c == 'a' || c == 'o' || c == 'u') {
                    lastExtendable = i;
                    break;
                }
            }
            if (lastExtendable >= 0) {
                char ext = str.charAt(lastExtendable);
                return (
                    str.substring(0, lastExtendable + 1) +
                    ext +
                    ext +
                    str.substring(lastExtendable + 1)
                );
            }
        }

        return result.toString();
    }

    /**
     * Get the intensity multiplier for an emotion.
     * Higher intensity = more muffling effect.
     *
     * @param emotion The emotion type
     * @return Intensity multiplier (1.0 = normal)
     */
    public static float getIntensityMultiplier(EmotionType emotion) {
        switch (emotion) {
            case SHOUTING:
                return 1.3f; // Harder to understand when shouting
            case WHISPERING:
                return 0.7f; // Easier (softer, clearer)
            case DISTRESSED:
                return 1.2f;
            case CRYING:
                return 1.4f;
            case LAUGHING:
                return 1.1f;
            case PLEADING:
            case QUESTIONING:
            case NORMAL:
            default:
                return 1.0f;
        }
    }

    /**
     * Check if the emotion should preserve more of the original text.
     * Some emotions (like whispering) are clearer.
     */
    public static boolean shouldPreserveMore(EmotionType emotion) {
        return emotion == EmotionType.WHISPERING;
    }
}
