<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Agent Chat Interface</title>
    <script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
    <link href="https://cdn.jsdelivr.net/npm/tailwindcss@2.2.19/dist/tailwind.min.css" rel="stylesheet">
    <link href="https://cdn.jsdelivr.net/npm/@tailwindcss/typography/dist/typography.min.css" rel="stylesheet">
    <script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
    <script src="https://cdn.plot.ly/plotly-2.27.0.min.js"></script>
    <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600&display=swap" rel="stylesheet">
    <style>
        .chat-message {
            transition: opacity 0.3s ease, transform 0.3s ease;
        }
        .chat-message-enter {
            opacity: 0;
            transform: translateY(10px);
        }
        .chat-message-enter-active {
            opacity: 1;
            transform: translateY(0);
        }
        .tool-section {
            transition: max-height 0.3s ease, opacity 0.3s ease;
        }
        .tool-section.collapsed {
            max-height: 0;
            opacity: 0;
            overflow: hidden;
        }
        .tool-section.expanded {
            max-height: 1000px;
            opacity: 1;
        }
        pre code {
            display: block;
            background: #f5f5f5;
            padding: 1rem;
            border-radius: 0.5rem;
            overflow-x: auto;
        }
    </style>
</head>
<body class="bg-gray-50 font-inter">
    <div id="app" class="min-h-screen flex flex-col">
        <div class="max-w-4xl mx-auto p-4 flex-1 flex flex-col w-full">
            <!-- Chat Messages -->
            <div class="bg-white rounded-lg shadow-lg p-6 mb-4 flex-1 overflow-y-auto w-full">
                <div v-for="(message, index) in messages" :key="index" class="chat-message mb-4">
                    <!-- User Message -->
                    <div v-if="message.role === 'user'" class="flex justify-end">
                        <div class="bg-blue-500 text-white rounded-lg py-2 px-4 max-w-[80%] shadow-sm">
                            {{ message.content }}
                        </div>
                    </div>

                    <!-- Assistant Message -->
                    <div v-else class="flex flex-col space-y-2">
                        <!-- Regular Message -->
                        <div v-if="message.content" class="bg-gray-100 rounded-lg py-2 px-4 max-w-[80%] shadow-sm prose">
                            <div v-html="formatMarkdown(message.content)"></div>
                        </div>

                        <!-- Tool Execution -->
                        <div v-if="message.tool_data" class="border border-gray-200 rounded-lg p-4 max-w-[80%] shadow-sm">
                            <div class="flex items-center justify-between cursor-pointer" 
                                 @click="toggleTool(index)">
                                <h3 class="font-semibold text-gray-700">
                                    Tool: {{ message.tool_data.tool }}
                                </h3>
                                <span class="text-gray-500">
                                    {{ isToolExpanded(index) ? '▼' : '▶' }}
                                </span>
                            </div>
                            
                            <div :class="['tool-section', isToolExpanded(index) ? 'expanded' : 'collapsed']">
                                <!-- Tool Input -->
                                <div v-if="message.tool_data.input" class="mt-2">
                                    <div class="text-sm text-gray-600">Input:</div>
                                    <pre v-if="message.tool_data.tool === 'execute_python'"><code>{{ message.tool_data.input.code }}</code></pre>
                                    <pre v-else class="bg-gray-50 p-2 rounded mt-1 text-sm overflow-x-auto">{{ JSON.stringify(message.tool_data.input, null, 2) }}</pre>
                                </div>

                                <!-- Tool Output -->
                                <div v-if="message.tool_data.output" class="mt-2">
                                    <div class="text-sm text-gray-600">Output:</div>
                                    <div v-if="message.tool_data.output.artifacts" class="space-y-4">
                                        <div v-for="(artifact, artifactIndex) in message.tool_data.output.artifacts" 
                                             :key="artifact.artifact_id"
                                             class="mt-4">
                                            <!-- Image Artifact -->
                                            <img v-if="artifact.artifact_type.startsWith('image/')"
                                                 :src="artifact.imageData ? `data:${artifact.artifact_type};base64,${artifact.imageData}` : ''"
                                                 class="max-w-full h-auto rounded shadow-sm"
                                                 :alt="artifact.artifact_id">
                                            
                                            <!-- Plotly Artifact -->
                                            <div v-else-if="artifact.artifact_type === 'application/vnd.plotly.v1+json'"
                                                 :id="'plot-' + index + '-' + artifactIndex"
                                                 class="w-full h-96">
                                            </div>

                                            <!-- HTML Artifact -->
                                            <div v-else-if="artifact.artifact_type === 'text/html'"
                                                 class="border rounded p-2 bg-gray-50 shadow-sm"
                                                 v-html="artifact.content">
                                            </div>
                                        </div>
                                    </div>
                                    <pre v-if="message.tool_data.output.text" 
                                         class="bg-gray-50 p-2 rounded mt-1 text-sm overflow-x-auto shadow-sm">{{ message.tool_data.output.text }}</pre>
                                </div>
                            </div>
                        </div>
                    </div>
                </div>
            </div>

            <!-- Input Area -->
            <div class="flex space-x-4">
                <input v-model="userInput"
                       @keyup.enter="sendMessage"
                       type="text"
                       class="flex-1 rounded-lg border border-gray-300 p-2 focus:outline-none focus:ring-2 focus:ring-blue-500 shadow-sm"
                       placeholder="Type your message...">
                <button @click="sendMessage"
                        class="bg-blue-500 text-white px-6 py-2 rounded-lg hover:bg-blue-600 focus:outline-none focus:ring-2 focus:ring-blue-500 shadow-sm">
                    Send
                </button>
            </div>
        </div>
    </div>

    <script>
        const { createApp } = Vue

        createApp({
            data() {
                return {
                    messages: [],
                    userInput: '',
                    expandedTools: new Set(),
                    currentAssistantMessage: '',
                    session_token: crypto.randomUUID()
                }
            },
            methods: {
                formatMarkdown(text) {
                    return marked.parse(text)
                },
                toggleTool(index) {
                    if (this.expandedTools.has(index)) {
                        this.expandedTools.delete(index)
                    } else {
                        this.expandedTools.add(index)
                        // Re-render Plotly charts when expanding, only if they haven't been rendered
                        this.$nextTick(() => {
                            const message = this.messages[index]
                            if (message?.tool_data?.output?.artifacts) {
                                const needsRendering = message.tool_data.output.artifacts.some(artifact => {
                                    if (artifact.artifact_type === 'application/vnd.plotly.v1+json') {
                                        const elementId = `plot-${index}-${message.tool_data.output.artifacts.indexOf(artifact)}`
                                        const element = document.getElementById(elementId)
                                        return element && !element._fullData
                                    }
                                    return false
                                })
                                if (needsRendering) {
                                    this.renderPlotlyCharts(index)
                                }
                            }
                        })
                    }
                },
                isToolExpanded(index) {
                    return this.expandedTools.has(index)
                },
                async fetchArtifact(artifactId) {
                    try {
                        const response = await fetch(`https://pvanand-code-execution-files-v5.hf.space/artifact/${artifactId}`)
                        if (!response.ok) throw new Error('Failed to fetch artifact')
                        const data = await response.json()
                        return data
                    } catch (error) {
                        console.error('Error fetching artifact:', error)
                        return null
                    }
                },
                renderPlotlyCharts(messageIndex) {
                    const message = this.messages[messageIndex]
                    if (!message?.tool_data?.output?.artifacts) return

                    message.tool_data.output.artifacts.forEach((artifact, artifactIndex) => {
                        if (artifact.artifact_type === 'application/vnd.plotly.v1+json' && artifact.plotData) {
                            const elementId = `plot-${messageIndex}-${artifactIndex}`
                            const element = document.getElementById(elementId)
                            if (element) {
                                // Check if a plot already exists in this element
                                if (element._fullData) {
                                    // Update existing plot
                                    Plotly.react(elementId, artifact.plotData)
                                } else {
                                    // Create new plot
                                    Plotly.newPlot(elementId, artifact.plotData)
                                }
                            }
                        }
                    })
                },
                async handleToolEnd(eventData) {
                    // Create a new message for each tool output
                    const newMessage = {
                        role: 'assistant',
                        tool_data: {
                            tool: eventData.tool,
                            output: {
                                text: eventData.output.text,
                                artifacts: []
                            }
                        }
                    }

                    if (eventData.output?.artifacts) {
                        for (const artifact of eventData.output.artifacts) {
                            const data = await this.fetchArtifact(artifact.artifact_id)
                            
                            if (artifact.artifact_type.startsWith('image/')) {
                                artifact.imageData = data.data
                            }
                            else if (artifact.artifact_type === 'application/vnd.plotly.v1+json') {
                                artifact.plotData = JSON.parse(data.data)
                            }
                            else if (artifact.artifact_type === 'text/html') {
                                artifact.content = data.data
                            }
                            newMessage.tool_data.output.artifacts.push(artifact)
                        }
                    }

                    this.messages.push(newMessage)
                    // Expand the tool section automatically
                    this.expandedTools.add(this.messages.length - 1)
                    // Render Plotly charts after the DOM updates
                    this.$nextTick(() => {
                        this.renderPlotlyCharts(this.messages.length - 1)
                    })
                },
                async sendMessage() {
                    if (!this.userInput.trim()) return

                    // Add user message
                    this.messages.push({
                        role: 'user',
                        content: this.userInput
                    })

                    const data = {
                        message: this.userInput,
                        thread_id: this.session_token
                    }

                    this.userInput = ''
                    this.currentAssistantMessage = ''

                    try {
                        const response = await fetch('https://pvanand-code-chat-api.hf.space/chat', {
                            method: 'POST',
                            headers: {
                                'Content-Type': 'application/json',
                                'Accept': 'text/event-stream'
                            },
                            body: JSON.stringify(data)
                        })

                        const reader = response.body.getReader()

                        while (true) {
                            const { done, value } = await reader.read()
                            if (done) break

                            const chunk = new TextDecoder().decode(value)
                            const lines = chunk.split('\n')

                            for (const line of lines) {
                                if (!line.startsWith('data: ')) continue

                                try {
                                    const eventData = JSON.parse(line.substring(6))
                                    
                                    switch (eventData.type) {
                                        case 'token':
                                            this.handleToken(eventData)
                                            break
                                        case 'tool_start':
                                            this.handleToolStart(eventData)
                                            break
                                        case 'tool_end':
                                            await this.handleToolEnd(eventData)
                                            break
                                    }
                                } catch (e) {
                                    console.error('Error parsing event:', e)
                                }
                            }
                        }
                    } catch (error) {
                        console.error('Error:', error)
                    }
                },
                handleToken(eventData) {
                    this.currentAssistantMessage += eventData.content
                    this.updateAssistantMessage(this.currentAssistantMessage)
                },
                handleToolStart(eventData) {
                    // Only create a new message if it's a new tool execution
                    if (!this.messages.length || 
                        this.messages[this.messages.length - 1].role !== 'assistant' ||
                        this.messages[this.messages.length - 1].tool_data?.output) {
                        this.messages.push({
                            role: 'assistant',
                            tool_data: {
                                tool: eventData.tool,
                                input: eventData.input
                            }
                        })
                    }
                },
                updateAssistantMessage(content) {
                    const lastMessage = this.messages[this.messages.length - 1]
                    if (lastMessage?.role === 'assistant' && !lastMessage.tool_data) {
                        lastMessage.content = content
                    } else {
                        this.messages.push({
                            role: 'assistant',
                            content: content
                        })
                    }
                }
            },
            beforeUnmount() {
                // Clean up all Plotly charts when component is destroyed
                this.messages.forEach((message, index) => {
                    if (message?.tool_data?.output?.artifacts) {
                        message.tool_data.output.artifacts.forEach((artifact, artifactIndex) => {
                            if (artifact.artifact_type === 'application/vnd.plotly.v1+json') {
                                const elementId = `plot-${index}-${artifactIndex}`
                                Plotly.purge(elementId)
                            }
                        })
                    }
                })
            }
        }).mount('#app')
    </script>
</body>
</html>