<script lang="ts">
    import { marked } from 'marked';

    export let gradio: any;
    export let elem_id: string = "";
    export let elem_classes: string[] = [];
    export let visible: boolean = true;
    export let value: string = "{}";
    export let label: string = "Consilium Roundtable";
    export let label_icon: string | null = "🎭";
    export let show_label: boolean = true;
    export let scale: number | null = null;
    export let min_width: number | undefined = undefined;

    $: containerClasses = `wrapper ${elem_classes.join(' ')}`;
    $: containerStyle = scale ? `--scale: ${scale}` : '';
    $: minWidthStyle = min_width ? `min-width: ${min_width}px` : '';

    let participants = [];
    let messages = [];
    let currentSpeaker = null;
    let thinking = [];
    let showBubbles = [];
    let avatarImages = {};
    
    function updateFromValue() {
        try {
            const parsedValue = JSON.parse(value);
            
            participants = parsedValue.participants || [];
            messages = parsedValue.messages || [];
            currentSpeaker = parsedValue.currentSpeaker || null;
            thinking = parsedValue.thinking || [];
            showBubbles = parsedValue.showBubbles || [];
            avatarImages = parsedValue.avatarImages || {};
            
            console.log("Clean JSON parsed:", {participants, messages, currentSpeaker, thinking, showBubbles, avatarImages});
        } catch (e) {
            console.error("Invalid JSON:", value, e);
        }
    }

    function renderMarkdown(text: string): string {
        if (!text) return text;
        
        try {
            // Configure marked for inline rendering
            marked.setOptions({
                breaks: true,        // Convert line breaks to <br>
                gfm: true,          // GitHub flavored markdown
                sanitize: false,    // Allow HTML (safe since we control input)
                smartypants: false  // Don't convert quotes/dashes
            });
            
            // For single lines, parse as inline; for multi-line, parse as block
            const hasMultipleLines = text.includes('\n');
            
            if (hasMultipleLines) {
                return marked.parse(text);
            } else {
                return marked.parseInline(text);
            }
        } catch (error) {
            console.error('Markdown parsing error:', error);
            return text; // Fallback to plain text
        }
    }
    
    $: value, updateFromValue();
    
    const avatarEmojis = {
        "Anthropic": "🤖",
        "Claude": "🤖",
        "Search": "🔍",
        "Web Search Agent": "🔍",
        "OpenAI": "🧠",
        "GPT-4": "🧠", 
        "Google": "💎",
        "Gemini": "💎",
        "QwQ-32B": "😊",
        "DeepSeek-R1": "🔮",
        "Mistral": "🐱",
        "Mistral Large": "🐱",
        "Meta-Llama-3.1-8B": "🦙"
    };
    
    function getEmoji(name: string) {
        return avatarEmojis[name] || "🤖";
    }

    function getAvatarImageUrl(name: string) {
        return avatarImages[name] || null;
    }

    function hasCustomImage(name: string) {
        return avatarImages[name] && avatarImages[name].trim() !== '';
    }
    
    function getLatestMessage(speaker: string) {
        if (thinking.includes(speaker)) {
            return `${speaker} is thinking...`;
        }
        if (currentSpeaker === speaker) {
            return `${speaker} is responding...`;
        }
        
        const speakerMessages = messages.filter(m => m.speaker === speaker);
        if (speakerMessages.length === 0) {
            return `${speaker} is ready to discuss...`;
        }
        return speakerMessages[speakerMessages.length - 1].text || `${speaker} responded`;
    }
    
    function isBubbleVisible(speaker: string) {
        const isThinking = thinking.includes(speaker);
        const isSpeaking = currentSpeaker === speaker;
        const shouldShow = showBubbles.includes(speaker);
        const visible = isThinking || isSpeaking || shouldShow;
        
        console.log(`${speaker} bubble visible:`, visible, {isThinking, isSpeaking, shouldShow});
        return visible;
    }
    
    function isAvatarActive(speaker: string) {
        return thinking.includes(speaker) || currentSpeaker === speaker;
    }
    
    function getPosition(index: number, total: number) {
        const angle = (360 / total) * index;
        const radians = (angle - 90) * (Math.PI / 180);
        
        const radiusX = 260;
        const radiusY = 180;
        
        const x = Math.cos(radians) * radiusX;
        const y = Math.sin(radians) * radiusY;
        
        return {
            left: `calc(50% + ${x}px)`,
            top: `calc(50% + ${y}px)`,
            transform: 'translate(-50%, -50%)'
        };
    }

    function handleImageError(event: Event, participant: string) {
        console.warn(`Failed to load avatar image for ${participant}, falling back to emoji`);
        // Hide the image and show emoji by removing the image URL
        avatarImages = {...avatarImages, [participant]: null};
    }

    function handleLabelIconError(event: Event) {
        console.warn('Failed to load label icon image, falling back to default emoji');
        // Set to null to trigger emoji fallback
        label_icon = null;
    }

    function isImageUrl(str: string | null): boolean {
        if (!str) return false;
        return str.startsWith('http://') || str.startsWith('https://') || str.startsWith('data:');
    }
</script>

<div 
    class={containerClasses} 
    class:hidden={!visible} 
    id={elem_id}
    style="{containerStyle}; {minWidthStyle}"
>   
    <div class="consilium-container" id="consilium-roundtable">
        <div class="table-center">
            {#if show_label && label}
                <label class="block-title" for="consilium-roundtable">
                    {#if label_icon}
                        <div class="label-icon-container">
                            {#if isImageUrl(label_icon)}
                                <img 
                                    src={label_icon} 
                                    alt="Label Icon" 
                                    class="label-icon-image"
                                    on:error={handleLabelIconError}
                                />
                            {:else}
                                <span class="label-icon-emoji">{label_icon}</span>
                            {/if}
                        </div>
                    {/if}
                    {label}
                </label>
            {/if}
        </div>
        
        <div class="participants-circle">
            {#each participants as participant, index}
                <div 
                    class="participant-seat" 
                    style="left: {getPosition(index, participants.length).left}; top: {getPosition(index, participants.length).top}; transform: {getPosition(index, participants.length).transform};"
                >
                    <div class="speech-bubble" class:visible={isBubbleVisible(participant)}>
                        <div class="bubble-content">{@html renderMarkdown(getLatestMessage(participant))}</div>
                        <div class="bubble-arrow"></div>
                    </div>
                    
                    <div 
                        class="avatar" 
                        class:speaking={isAvatarActive(participant)}
                        class:thinking={thinking.includes(participant)}
                        class:responding={currentSpeaker === participant}
                        class:has-image={hasCustomImage(participant)}
                        role="button"
                        tabindex="0"
                    >
                        {#if hasCustomImage(participant)}
                            <img 
                                src={getAvatarImageUrl(participant)} 
                                alt={participant}
                                class="avatar-image"
                                on:error={(event) => handleImageError(event, participant)}
                            />
                        {:else}
                            <span class="avatar-emoji">{getEmoji(participant)}</span>
                        {/if}
                    </div>
                    <div class="participant-name">{participant}</div>
                </div>
            {/each}
        </div>
    </div>
</div>

<style>
    .hidden {
        display: none;
    }
    
    .block-title {
        padding: 10px;
        font-weight: bold;
        color: #ffd700;
        display: flex;
        flex-wrap: wrap;
        justify-content: center;
        text-shadow: 0 2px 4px rgba(0,0,0,0.8);
    }

    .label-icon-container {
        width: 24px;
        height: 24px;
    }

    .label-icon-emoji {
        font-size: 1.2rem;
        line-height: 1;
    }

    .label-icon-image {
        width: 24px;
        height: 24px;
        object-fit: contain;
        border-radius: 4px;
    }

    .wrapper {
        width: 600px;
        height: 600px;
        position: relative;
    }

    .consilium-container {
        top: 190px;
        position: relative;
        width: 450px;
        height: 300px;
        margin: 20px auto;
        border-radius: 50%;
        background: linear-gradient(135deg, #0f5132, #198754);
        border: 8px solid #8b4513;
        box-shadow: 
            0 8px 32px rgba(0,0,0,0.4),
            inset 0 0 20px rgba(0,0,0,0.2);
    }

    .table-center {
        position: absolute;
        top: 50%;
        left: 50%;
        transform: translate(-50%, -50%);
        text-align: center;
        background: rgba(0,0,0,0.3);
        border-radius: 50%;
        width: 140px;
        height: 100px; 
        display: flex;
        flex-direction: column;
        align-items: center;
        justify-content: center;
        border: 2px solid #8b4513;
        box-shadow: inset 0 0 10px rgba(0,0,0,0.5);
    }

    .participant-seat {
        position: absolute;
        display: flex;
        flex-direction: column;
        align-items: center;
    }

    .avatar {
        width: 60px;
        height: 60px;
        border-radius: 50%;
        display: flex;
        align-items: center;
        justify-content: center;
        font-size: 1.4rem;
        background: linear-gradient(145deg, #ffffff, #e6e6e6);
        border: 3px solid #8b4513;
        box-shadow: 
            0 6px 15px rgba(0,0,0,0.3),
            inset 0 2px 5px rgba(255,255,255,0.5);
        margin-bottom: 8px;
        transition: all 0.3s ease;
        position: relative;
        z-index: 10;
        overflow: hidden;
    }

    .avatar.has-image {
        background: #f8f9fa;
        padding: 2px;
    }

    .avatar-image {
        width: 100%;
        height: 100%;
        object-fit: cover;
        border-radius: 50%;
    }

    .avatar-emoji {
        font-size: 1.4rem;
        line-height: 1;
    }

    .avatar.thinking {
        border-color: #ff6b35;
        animation: thinking-pulse 1.5s infinite;
    }

    .avatar.responding {
        border-color: #ffd700;
        animation: speaking-glow 1s infinite;
    }

    .avatar.speaking {
        border-color: #ffd700;
    }

    .participant-name {
        font-size: 0.75rem;
        font-weight: bold;
        color: #ffd700;
        text-shadow: 0 2px 4px rgba(0,0,0,0.8);
        text-align: center;
        white-space: nowrap;
        background: rgba(0,0,0,0.3);
        padding: 2px 8px;
        border-radius: 10px;
        border: 1px solid #8b4513;
    }

    .speech-bubble {
        position: absolute;
        bottom: 90px;
        left: 50%;
        transform: translateX(-50%) translateY(20px);
        background: white;
        border-radius: 15px;
        padding: 10px 14px;
        box-shadow: 0 8px 25px rgba(0,0,0,0.3);
        z-index: 20;
        opacity: 0;
        transition: all 0.4s ease;
        pointer-events: none;
        border: 2px solid #8b4513;
        min-width: 180px;
        max-width: 300px;
        word-wrap: break-word;
        white-space: normal;
    }

    .speech-bubble.visible {
        opacity: 1;
        transform: translateX(-50%) translateY(0);
        pointer-events: auto;
    }

    .bubble-content {
        font-size: 0.8rem;
        color: #333;
        line-height: 1.4;
        text-align: left;
        max-height: 100px;
        overflow-y: auto;
        scrollbar-width: thin;
        scrollbar-color: #8b4513 #f0f0f0;
    }

    .bubble-content::-webkit-scrollbar {
        width: 6px;
    }

    .bubble-content::-webkit-scrollbar-track {
        background: #f0f0f0;
        border-radius: 3px;
    }

    .bubble-content::-webkit-scrollbar-thumb {
        background: #8b4513;
        border-radius: 3px;
    }

    .bubble-content::-webkit-scrollbar-thumb:hover {
        background: #654321;
    }

    .bubble-arrow {
        position: absolute;
        bottom: -10px;
        left: 50%;
        transform: translateX(-50%);
        width: 0;
        height: 0;
        border-left: 10px solid transparent;
        border-right: 10px solid transparent;
        border-top: 10px solid white;
    }

    .bubble-arrow::before {
        content: '';
        position: absolute;
        bottom: 2px;
        left: 50%;
        transform: translateX(-50%);
        width: 0;
        height: 0;
        border-left: 12px solid transparent;
        border-right: 12px solid transparent;
        border-top: 12px solid #8b4513;
    }

    @keyframes thinking-pulse {
        0%, 100% { 
            transform: scale(1);
            box-shadow: 0 6px 15px rgba(0,0,0,0.3), 0 0 15px rgba(255, 107, 53, 0.4);
        }
        50% { 
            transform: scale(1.03);
            box-shadow: 0 8px 20px rgba(0,0,0,0.4), 0 0 25px rgba(255, 107, 53, 0.6);
        }
    }

    @keyframes speaking-glow {
        0%, 100% { 
            box-shadow: 0 6px 15px rgba(0,0,0,0.3), 0 0 20px rgba(255, 215, 0, 0.5);
        }
        50% { 
            box-shadow: 0 8px 20px rgba(0,0,0,0.4), 0 0 30px rgba(255, 215, 0, 0.8);
        }
    }
</style>