<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="s" uri="/struts-tags" %>
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>OGNL表达式可视化 - 对象图导航语言</title>
    <style>
        * { margin: 0; padding: 0; box-sizing: border-box; }
        body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; background: #f5f7fa; padding: 20px; }
        .container { max-width: 1400px; margin: 0 auto; }
        
        .header { background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; padding: 30px; border-radius: 15px; margin-bottom: 30px; text-align: center; }
        .header h1 { font-size: 2em; margin-bottom: 10px; }
        
        .grid { display: grid; grid-template-columns: 1fr 1fr; gap: 20px; margin-bottom: 30px; }
        @media (max-width: 900px) { .grid { grid-template-columns: 1fr; } }
        
        .card { background: white; border-radius: 12px; padding: 25px; box-shadow: 0 4px 20px rgba(0,0,0,0.08); }
        .card h3 { color: #333; margin-bottom: 15px; border-bottom: 2px solid #eee; padding-bottom: 10px; }
        
        /* 表达式编辑器 */
        .expression-editor { margin-bottom: 20px; }
        .expression-input { 
            width: 100%; 
            padding: 15px; 
            font-size: 16px; 
            font-family: 'Monaco', monospace;
            border: 2px solid #ddd; 
            border-radius: 8px;
            margin-bottom: 10px;
        }
        .expression-input:focus { outline: none; border-color: #667eea; }
        
        .btn { padding: 12px 24px; border: none; border-radius: 6px; cursor: pointer; font-size: 14px; transition: all 0.3s; }
        .btn-primary { background: #667eea; color: white; }
        .btn-primary:hover { background: #5a6fd6; }
        .btn-secondary { background: #95a5a6; color: white; margin-left: 10px; }
        .btn-secondary:hover { background: #7f8c8d; }
        
        /* 结果显示 */
        .result-panel { 
            background: #1e1e1e; 
            color: #d4d4d4; 
            padding: 20px; 
            border-radius: 8px;
            font-family: 'Monaco', monospace;
            min-height: 150px;
        }
        .result-success { border-left: 4px solid #27ae60; }
        .result-error { border-left: 4px solid #e74c3c; }
        .result-label { color: #999; font-size: 12px; margin-bottom: 5px; }
        .result-value { color: #67eea; font-size: 14px; word-break: break-all; }
        .result-type { color: #f39c12; font-size: 12px; margin-top: 10px; }
        .result-error-msg { color: #e74c3c; }
        
        /* 示例列表 */
        .examples-list { max-height: 500px; overflow-y: auto; }
        .example-item { 
            background: #f8f9fa; 
            border-radius: 8px; 
            padding: 15px; 
            margin-bottom: 10px;
            cursor: pointer;
            transition: all 0.3s;
            border-left: 3px solid transparent;
        }
        .example-item:hover { 
            background: #e8f4f8; 
            border-left-color: #3498db;
            transform: translateX(5px);
        }
        .example-category { 
            display: inline-block; 
            padding: 3px 10px; 
            border-radius: 12px; 
            font-size: 11px; 
            margin-bottom: 8px;
            background: #667eea;
            color: white;
        }
        .example-expression { 
            font-family: 'Monaco', monospace;
            font-size: 14px;
            color: #333;
            margin-bottom: 5px;
            font-weight: bold;
        }
        .example-desc { font-size: 12px; color: #666; }
        .example-result { font-size: 11px; color: #27ae60; margin-top: 5px; }
        
        /* 数据结构展示 */
        .data-structure { background: #f8f9fa; border-radius: 8px; padding: 15px; }
        .data-object { margin-bottom: 15px; }
        .data-object-header { 
            background: #667eea; 
            color: white; 
            padding: 8px 12px; 
            border-radius: 6px;
            font-weight: bold;
            cursor: pointer;
        }
        .data-object-content { 
            padding: 10px; 
            border: 1px solid #e0e0e0; 
            border-top: none;
            border-radius: 0 0 6px 6px;
            background: white;
        }
        .data-field { 
            display: flex; 
            justify-content: space-between; 
            padding: 5px 0;
            border-bottom: 1px solid #f0f0f0;
        }
        .data-field:last-child { border-bottom: none; }
        .data-field-name { color: #667eea; font-weight: 500; }
        .data-field-value { color: #333; }
        .data-field-type { color: #999; font-size: 11px; }
        
        /* 语法树 */
        .syntax-tree { display: flex; flex-direction: column; gap: 10px; }
        .tree-node { 
            background: #f8f9fa; 
            border-radius: 8px; 
            padding: 12px 15px;
            border-left: 3px solid #667eea;
        }
        .tree-node-root { background: #667eea; color: white; border-left: none; }
        .tree-node-title { font-weight: bold; margin-bottom: 5px; }
        .tree-node-example { font-size: 12px; opacity: 0.8; font-family: monospace; }
        
        /* 快速操作按钮 */
        .quick-actions { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 15px; }
        .quick-btn { 
            padding: 6px 12px; 
            background: #e8f4f8; 
            border: 1px solid #3498db;
            border-radius: 15px;
            font-size: 12px;
            cursor: pointer;
            transition: all 0.3s;
        }
        .quick-btn:hover { background: #3498db; color: white; }
        
        .nav { display: flex; gap: 10px; margin-bottom: 20px; flex-wrap: wrap; }
        .nav a { padding: 10px 20px; background: white; border-radius: 20px; text-decoration: none; color: #333; font-size: 0.9em; box-shadow: 0 2px 5px rgba(0,0,0,0.1); }
        .nav a:hover { background: #667eea; color: white; }
        
        .lab { background: #fff7e6; border-left: 4px solid #fa8c16; padding: 15px; border-radius: 8px; margin-bottom: 20px; }
        .lab strong { color: #874d00; }
        
        .tips { background: #e8f4f8; padding: 15px; border-radius: 8px; margin-top: 15px; }
        .tips ul { margin-left: 20px; }
        .tips li { margin-bottom: 5px; font-size: 13px; }
    </style>
</head>
<body>
    <div class="container">
        <div class="header">
            <h1>🎯 OGNL表达式可视化</h1>
            <p>交互式学习对象图导航语言（Object-Graph Navigation Language）</p>
        </div>
        
        <div class="nav">
            <a href="index.jsp">← 返回首页</a>
            <a href="learn">学习中心</a>
            <a href="classloader-visual">类加载可视化</a>
            <a href="lifecycle">生命周期可视化</a>
        </div>
        
        <div class="lab">
            <strong>🧪 实验任务</strong>
            <ul>
                <li>在<strong>表达式编辑器</strong>中输入OGNL表达式，观察执行结果</li>
                <li>点击<strong>示例列表</strong>中的表达式，快速学习各种语法</li>
                <li>查看<strong>测试数据结构</strong>，了解可以访问的数据</li>
                <li>尝试组合使用过滤、投影等高级操作</li>
            </ul>
        </div>
        
        <div class="grid">
            <!-- 表达式编辑器 -->
            <div class="card">
                <h3>✏️ 表达式编辑器</h3>
                <div class="expression-editor">
                    <input type="text" id="expressionInput" class="expression-input" 
                           placeholder="输入OGNL表达式，例如: user.name 或 users.{name}">
                    <div>
                        <button class="btn btn-primary" onclick="executeExpression()">执行表达式</button>
                        <button class="btn btn-secondary" onclick="clearExpression()">清空</button>
                    </div>
                </div>
                
                <h4 style="margin-top: 20px; margin-bottom: 10px;">执行结果</h4>
                <div id="resultPanel" class="result-panel">
                    <div class="result-label">输入表达式并点击"执行"查看结果</div>
                </div>
                
                <div class="quick-actions">
                    <span style="font-size: 12px; color: #666; margin-right: 10px;">快速插入:</span>
                    <span class="quick-btn" onclick="insertExpression('user.name')">user.name</span>
                    <span class="quick-btn" onclick="insertExpression('user.address.city')">user.address.city</span>
                    <span class="quick-btn" onclick="insertExpression('users.size()')">users.size()</span>
                    <span class="quick-btn" onclick="insertExpression('users.{name}')">users.{name}</span>
                    <span class="quick-btn" onclick="insertExpression('users.{? #this.age > 25}')">过滤</span>
                    <span class="quick-btn" onclick="insertExpression('#sessionUser.name')">#sessionUser</span>
                </div>
            </div>
            
            <!-- 示例列表 -->
            <div class="card">
                <h3>📚 OGNL示例库（点击使用）</h3>
                <div id="examplesList" class="examples-list">
                    <div style="text-align: center; padding: 20px; color: #999;">加载中...</div>
                </div>
            </div>
            
            <!-- 测试数据结构 -->
            <div class="card">
                <h3>📦 测试数据结构</h3>
                <div id="dataStructure" class="data-structure">
                    <div style="text-align: center; padding: 20px; color: #999;">加载中...</div>
                </div>
            </div>
            
            <!-- OGNL语法 -->
            <div class="card">
                <h3>🌲 OGNL语法类型</h3>
                <div id="syntaxTree" class="syntax-tree">
                    <div style="text-align: center; padding: 20px; color: #999;">加载中...</div>
                </div>
                
                <div class="tips">
                    <strong>💡 提示</strong>
                    <ul>
                        <li><strong>属性访问:</strong> 使用点号(.)访问对象属性，如 user.name</li>
                        <li><strong>方法调用:</strong> 直接调用方法，如 user.getName() 或 users.size()</li>
                        <li><strong>集合投影:</strong> 使用.{prop}提取属性列表，如 users.{name}</li>
                        <li><strong>集合过滤:</strong> 使用.{? condition}过滤元素</li>
                        <li><strong>上下文访问:</strong> 使用#访问上下文变量，如 #sessionUser</li>
                        <li><strong>静态访问:</strong> 使用@访问静态成员，如 @java.lang.Math@PI</li>
                    </ul>
                </div>
            </div>
        </div>
        
        <div class="card">
            <h3>📖 学习要点</h3>
            <ul>
                <li><strong>值栈根对象:</strong> Action对象默认在值栈顶部，可以直接访问其属性</li>
                <li><strong>OGNL上下文:</strong> 包含request、session、application等Web对象</li>
                <li><strong>类型转换:</strong> OGNL自动进行字符串到目标类型的转换</li>
                <li><strong>集合操作:</strong> 支持过滤(?)、投影(.{})、选择(^/$)等高级操作</li>
                <li><strong>Lambda支持:</strong> 可以使用Lambda表达式进行复杂操作</li>
                <li><strong>安全性:</strong> OGNL功能强大，注意防范OGNL注入攻击</li>
            </ul>
        </div>
    </div>
    
    <script>
        // 加载示例列表
        async function loadExamples() {
            try {
                const response = await fetch('ognl_getExamples');
                const data = await response.json();
                
                const container = document.getElementById('examplesList');
                container.innerHTML = '';
                
                data.examples.forEach((example, index) => {
                    const div = document.createElement('div');
                    div.className = 'example-item';
                    div.style.animationDelay = `${index * 0.05}s`;
                    div.onclick = () => useExample(example.expression);
                    
                    div.innerHTML = `
                        <span class="example-category">${example.category}</span>
                        <div class="example-expression">${example.expression}</div>
                        <div class="example-desc">${example.description}</div>
                        <div class="example-result">结果: ${example.expectedResult}</div>
                    `;
                    
                    container.appendChild(div);
                });
            } catch (error) {
                document.getElementById('examplesList').innerHTML = 
                    `<div style="color: #e74c3c;">加载失败: ${error.message}</div>`;
            }
        }
        
        // 加载测试数据
        async function loadTestData() {
            try {
                const response = await fetch('ognl_getTestData');
                const data = await response.json();
                
                const container = document.getElementById('dataStructure');
                container.innerHTML = '';
                
                // User对象
                const userDiv = document.createElement('div');
                userDiv.className = 'data-object';
                userDiv.innerHTML = `
                    <div class="data-object-header" onclick="toggleDataObject(this)">user: User</div>
                    <div class="data-object-content">
                        <div class="data-field">
                            <span class="data-field-name">id</span>
                            <span class="data-field-value">${data.user.id}</span>
                            <span class="data-field-type">Long</span>
                        </div>
                        <div class="data-field">
                            <span class="data-field-name">name</span>
                            <span class="data-field-value">${data.user.name}</span>
                            <span class="data-field-type">String</span>
                        </div>
                        <div class="data-field">
                            <span class="data-field-name">email</span>
                            <span class="data-field-value">${data.user.email}</span>
                            <span class="data-field-type">String</span>
                        </div>
                        <div class="data-field">
                            <span class="data-field-name">age</span>
                            <span class="data-field-value">${data.user.age}</span>
                            <span class="data-field-type">Integer</span>
                        </div>
                        <div class="data-field">
                            <span class="data-field-name">address</span>
                            <span class="data-field-value">${data.user.address.city} ${data.user.address.district}</span>
                            <span class="data-field-type">Address</span>
                        </div>
                    </div>
                `;
                container.appendChild(userDiv);
                
                // Users列表
                const usersDiv = document.createElement('div');
                usersDiv.className = 'data-object';
                usersDiv.innerHTML = `
                    <div class="data-object-header" onclick="toggleDataObject(this)">users: List&lt;User&gt; [${data.users.length} items]</div>
                    <div class="data-object-content" style="display: none;">
                        ${data.users.map(u => `
                            <div class="data-field">
                                <span class="data-field-name">${u.name}</span>
                                <span class="data-field-value">${u.age}岁, ${u.address.city}</span>
                            </div>
                        `).join('')}
                    </div>
                `;
                container.appendChild(usersDiv);
                
                // Context
                const contextDiv = document.createElement('div');
                contextDiv.className = 'data-object';
                contextDiv.innerHTML = `
                    <div class="data-object-header" onclick="toggleDataObject(this)">context: Map</div>
                    <div class="data-object-content" style="display: none;">
                        ${Object.entries(data.context).map(([k, v]) => `
                            <div class="data-field">
                                <span class="data-field-name">${k}</span>
                                <span class="data-field-value">${typeof v === 'object' ? JSON.stringify(v) : v}</span>
                            </div>
                        `).join('')}
                    </div>
                `;
                container.appendChild(contextDiv);
                
            } catch (error) {
                document.getElementById('dataStructure').innerHTML = 
                    `<div style="color: #e74c3c;">加载失败: ${error.message}</div>`;
            }
        }
        
        // 加载语法树
        async function loadSyntaxTree() {
            try {
                const response = await fetch('ognl_getSyntaxTree');
                const data = await response.json();
                
                const container = document.getElementById('syntaxTree');
                container.innerHTML = '';
                
                data.nodes.forEach((node, index) => {
                    const rootDiv = document.createElement('div');
                    rootDiv.className = 'tree-node tree-node-root';
                    rootDiv.innerHTML = `
                        <div class="tree-node-title">${node.name}</div>
                        <div class="tree-node-example">${node.description || ''}</div>
                    `;
                    container.appendChild(rootDiv);
                    
                    if (node.children) {
                        node.children.forEach((child, childIndex) => {
                            const childDiv = document.createElement('div');
                            childDiv.className = 'tree-node';
                            childDiv.style.marginLeft = '20px';
                            childDiv.innerHTML = `
                                <div class="tree-node-title">${child.name}</div>
                                <div class="tree-node-example">${child.example}</div>
                            `;
                            container.appendChild(childDiv);
                        });
                    }
                });
            } catch (error) {
                document.getElementById('syntaxTree').innerHTML = 
                    `<div style="color: #e74c3c;">加载失败: ${error.message}</div>`;
            }
        }
        
        // 执行表达式
        async function executeExpression() {
            const expression = document.getElementById('expressionInput').value.trim();
            if (!expression) {
                showResult('请输入表达式', null, '请输入OGNL表达式');
                return;
            }
            
            try {
                const response = await fetch('ognl_execute', {
                    method: 'POST',
                    headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
                    body: 'expression=' + encodeURIComponent(expression)
                });
                
                const data = await response.json();
                
                if (data.success) {
                    showResult(expression, data.result, null, data.resultType);
                } else {
                    showResult(expression, null, data.error);
                }
            } catch (error) {
                showResult(expression, null, '请求失败: ' + error.message);
            }
        }
        
        // 显示结果
        function showResult(expression, result, error, resultType) {
            const panel = document.getElementById('resultPanel');
            
            if (error) {
                panel.className = 'result-panel result-error';
                panel.innerHTML = `
                    <div class="result-label">表达式</div>
                    <div class="result-value">${expression}</div>
                    <div class="result-label" style="margin-top: 15px;">错误</div>
                    <div class="result-error-msg">${error}</div>
                `;
            } else {
                panel.className = 'result-panel result-success';
                let resultStr = result;
                if (typeof result === 'object') {
                    resultStr = JSON.stringify(result, null, 2);
                }
                panel.innerHTML = `
                    <div class="result-label">表达式</div>
                    <div class="result-value">${expression}</div>
                    <div class="result-label" style="margin-top: 15px;">结果</div>
                    <div class="result-value">${resultStr}</div>
                    <div class="result-type">类型: ${resultType}</div>
                `;
            }
        }
        
        // 使用示例
        function useExample(expression) {
            document.getElementById('expressionInput').value = expression;
            executeExpression();
        }
        
        // 插入表达式
        function insertExpression(expr) {
            const input = document.getElementById('expressionInput');
            input.value = expr;
            input.focus();
        }
        
        // 清空表达式
        function clearExpression() {
            document.getElementById('expressionInput').value = '';
            document.getElementById('resultPanel').innerHTML = '<div class="result-label">输入表达式并点击"执行"查看结果</div>';
            document.getElementById('resultPanel').className = 'result-panel';
        }
        
        // 切换数据对象展开/收起
        function toggleDataObject(header) {
            const content = header.nextElementSibling;
            content.style.display = content.style.display === 'none' ? 'block' : 'none';
        }
        
        // 页面加载时初始化
        window.onload = function() {
            loadExamples();
            loadTestData();
            loadSyntaxTree();
            
            // 绑定回车键
            document.getElementById('expressionInput').addEventListener('keypress', function(e) {
                if (e.key === 'Enter') {
                    executeExpression();
                }
            });
        };
    </script>
</body>
</html>
