package com.example.struts2;

import com.opensymphony.xwork2.ActionSupport;
import org.apache.struts2.ServletActionContext;
import com.google.gson.Gson;
import ognl.Ognl;
import ognl.OgnlContext;
import ognl.OgnlException;
import java.io.PrintWriter;
import java.io.IOException;
import java.util.*;

/**
 * OGNL可视化Action - 交互式学习OGNL表达式
 * 
 * 学习点：
 * - OGNL语法和表达式
 * - 值栈访问机制
 * - 集合操作和投影
 */
public class OgnlVisualAction extends ActionSupport {
    
    private static final Gson gson = new Gson();
    private String expression;
    private Object result;
    private String error;
    
    // 测试数据
    private User user;
    private List<User> users;
    private Map<String, Object> context;
    
    public OgnlVisualAction() {
        // 初始化测试数据
        user = new User(1L, "张三", "zhangsan@example.com", 25, 
            new Address("北京", "朝阳区", "100000"));
        
        users = Arrays.asList(
            new User(1L, "张三", "zhangsan@example.com", 25, new Address("北京", "朝阳区", "100000")),
            new User(2L, "李四", "lisi@example.com", 30, new Address("上海", "浦东新区", "200000")),
            new User(3L, "王五", "wangwu@example.com", 28, new Address("广州", "天河区", "510000")),
            new User(4L, "赵六", "zhaoliu@example.com", 35, new Address("深圳", "南山区", "518000"))
        );
        
        context = new HashMap<>();
        context.put("sessionUser", user);
        context.put("appName", "Struts2学习平台");
        context.put("version", "1.0.0");
    }
    
    /**
     * 显示OGNL可视化页面
     */
    public String execute() {
        return SUCCESS;
    }
    
    /**
     * 执行OGNL表达式（AJAX）
     */
    public String executeExpression() {
        Map<String, Object> response = new LinkedHashMap<>();
        
        try {
            // 创建OGNL上下文
            OgnlContext ognlContext = new OgnlContext();
            ognlContext.setRoot(user);
            ognlContext.putAll(context);
            
            // 解析并执行表达式
            Object expr = Ognl.parseExpression(expression);
            Object value = Ognl.getValue(expr, ognlContext, user);
            
            response.put("success", true);
            response.put("expression", expression);
            response.put("result", value);
            response.put("resultType", value != null ? value.getClass().getSimpleName() : "null");
            
        } catch (OgnlException e) {
            response.put("success", false);
            response.put("expression", expression);
            response.put("error", e.getMessage());
        }
        
        writeJsonResponse(response);
        return NONE;
    }
    
    /**
     * 获取OGNL示例（AJAX）
     */
    public String getExamples() {
        Map<String, Object> result = new LinkedHashMap<>();
        List<Map<String, Object>> examples = new ArrayList<>();
        
        // 基础表达式
        addExample(examples, "基础属性访问", "user.name", 
            "访问user对象的name属性", "张三");
        addExample(examples, "链式属性访问", "user.address.city", 
            "访问嵌套对象的属性", "北京");
        addExample(examples, "方法调用", "user.getName()", 
            "调用getter方法", "张三");
        addExample(examples, "静态方法", "@java.lang.Math@random()", 
            "调用静态方法", "随机数");
        
        // 集合操作
        addExample(examples, "集合大小", "users.size()", 
            "获取集合大小", "4");
        addExample(examples, "集合过滤", "users.{? #this.age > 25}", 
            "过滤年龄大于25的用户", "[李四, 王五, 赵六]");
        addExample(examples, "集合投影", "users.{name}", 
            "提取所有用户的姓名", "[张三, 李四, 王五, 赵六]");
        addExample(examples, "集合选择", "users.{^ #this.age > 25}", 
            "选择第一个符合条件的元素", "李四");
        addExample(examples, "集合选择", "users.{$ #this.age > 25}", 
            "选择最后一个符合条件的元素", "赵六");
        
        // 上下文访问
        addExample(examples, "上下文变量", "#sessionUser.name", 
            "访问上下文中的sessionUser", "张三");
        addExample(examples, "根对象", "#root", 
            "访问根对象", "User对象");
        addExample(examples, "this引用", "users.{#this.name}", 
            "在投影中使用this引用", "[张三, 李四, 王五, 赵六]");
        
        // 高级操作
        addExample(examples, "创建集合", "{1, 2, 3, 4, 5}", 
            "创建List集合", "[1, 2, 3, 4, 5]");
        addExample(examples, "创建Map", "#{'name':'张三', 'age':25}", 
            "创建Map对象", "{name=张三, age=25}");
        addExample(examples, "投影+过滤", "users.{? #this.age > 25}.{name}", 
            "先过滤再投影", "[李四, 王五, 赵六]");
        addExample(examples, "Lambda表达式", "users.stream().filter(u -> u.age > 25).count()", 
            "使用Stream API", "3");
        
        result.put("examples", examples);
        result.put("totalExamples", examples.size());
        
        writeJsonResponse(result);
        return NONE;
    }
    
    /**
     * 获取测试数据（AJAX）
     */
    public String getTestData() {
        Map<String, Object> result = new LinkedHashMap<>();
        
        result.put("user", user);
        result.put("users", users);
        result.put("context", context);
        
        writeJsonResponse(result);
        return NONE;
    }
    
    /**
     * 获取OGNL语法树（AJAX）
     */
    public String getSyntaxTree() {
        Map<String, Object> result = new LinkedHashMap<>();
        List<Map<String, Object>> nodes = new ArrayList<>();
        
        // 根节点
        Map<String, Object> root = new LinkedHashMap<>();
        root.put("id", "root");
        root.put("name", "OGNL表达式");
        root.put("type", "root");
        root.put("children", Arrays.asList(
            createNode("property", "属性访问", "user.name, user.age"),
            createNode("method", "方法调用", "user.getName(), users.size()"),
            createNode("collection", "集合操作", "users.{name}, users.{? #this.age > 25}"),
            createNode("context", "上下文访问", "#sessionUser, #root"),
            createNode("static", "静态访问", "@java.lang.Math@PI"),
            createNode("constructor", "构造创建", "new com.example.User(), {1,2,3}")
        ));
        nodes.add(root);
        
        result.put("nodes", nodes);
        result.put("description", "OGNL表达式语法树结构");
        
        writeJsonResponse(result);
        return NONE;
    }
    
    /**
     * 辅助方法：创建节点
     */
    private Map<String, Object> createNode(String id, String name, String example) {
        Map<String, Object> node = new LinkedHashMap<>();
        node.put("id", id);
        node.put("name", name);
        node.put("example", example);
        return node;
    }
    
    /**
     * 辅助方法：添加示例
     */
    private void addExample(List<Map<String, Object>> examples, String category, 
            String expression, String description, String result) {
        Map<String, Object> example = new LinkedHashMap<>();
        example.put("category", category);
        example.put("expression", expression);
        example.put("description", description);
        example.put("expectedResult", result);
        examples.add(example);
    }
    
    /**
     * 辅助方法：写入JSON响应
     */
    private void writeJsonResponse(Map<String, Object> data) {
        try {
            ServletActionContext.getResponse().setContentType("application/json;charset=UTF-8");
            PrintWriter out = ServletActionContext.getResponse().getWriter();
            out.print(gson.toJson(data));
            out.flush();
            out.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    
    // Getters and Setters
    public String getExpression() { return expression; }
    public void setExpression(String expression) { this.expression = expression; }
    
    public Object getResult() { return result; }
    public void setResult(Object result) { this.result = result; }
    
    public String getError() { return error; }
    public void setError(String error) { this.error = error; }
    
    public User getUser() { return user; }
    public void setUser(User user) { this.user = user; }
    
    public List<User> getUsers() { return users; }
    public void setUsers(List<User> users) { this.users = users; }
    
    public Map<String, Object> getContext() { return context; }
    public void setContext(Map<String, Object> context) { this.context = context; }
    
    /**
     * 内部类：用户实体
     */
    public static class User {
        private Long id;
        private String name;
        private String email;
        private Integer age;
        private Address address;
        
        public User() {}
        
        public User(Long id, String name, String email, Integer age, Address address) {
            this.id = id;
            this.name = name;
            this.email = email;
            this.age = age;
            this.address = address;
        }
        
        public Long getId() { return id; }
        public void setId(Long id) { this.id = id; }
        public String getName() { return name; }
        public void setName(String name) { this.name = name; }
        public String getEmail() { return email; }
        public void setEmail(String email) { this.email = email; }
        public Integer getAge() { return age; }
        public void setAge(Integer age) { this.age = age; }
        public Address getAddress() { return address; }
        public void setAddress(Address address) { this.address = address; }
    }
    
    /**
     * 内部类：地址实体
     */
    public static class Address {
        private String city;
        private String district;
        private String zipCode;
        
        public Address() {}
        
        public Address(String city, String district, String zipCode) {
            this.city = city;
            this.district = district;
            this.zipCode = zipCode;
        }
        
        public String getCity() { return city; }
        public void setCity(String city) { this.city = city; }
        public String getDistrict() { return district; }
        public void setDistrict(String district) { this.district = district; }
        public String getZipCode() { return zipCode; }
        public void setZipCode(String zipCode) { this.zipCode = zipCode; }
    }
}
