"""
预设管理器
负责粒子效果预设的保存、加载和管理
"""

import os
import json
from typing import Dict, List, Optional, Any
from datetime import datetime
from panda3d.core import Vec3

class PresetManager:
    """
    预设管理器
    管理粒子效果的预设配置
    """
    
    def __init__(self, plugin_dir: str = None):
        """
        初始化预设管理器
        
        Args:
            plugin_dir: 插件目录路径
        """
        if plugin_dir is None:
            plugin_dir = os.path.dirname(os.path.dirname(__file__))
            
        self.plugin_dir = plugin_dir
        self.presets_dir = os.path.join(plugin_dir, "presets")
        
        # 确保预设目录存在
        os.makedirs(self.presets_dir, exist_ok=True)
        
        # 预设缓存
        self.presets_cache: Dict[str, Dict] = {}
        self.cache_dirty = True
        
        # 内置预设
        self.builtin_presets = self._create_builtin_presets()
        
        print(f"✓ 预设管理器初始化完成，预设目录: {self.presets_dir}")
        
    def _create_builtin_presets(self) -> Dict[str, Dict]:
        """创建内置预设"""
        return {
            "经典火焰": {
                "metadata": {
                    "name": "经典火焰",
                    "description": "经典的火焰效果",
                    "author": "EG Team",
                    "version": "1.0",
                    "created": "2024-10-28",
                    "builtin": True
                },
                "config": {
                    "emitter_type": "fire",
                    "emission_rate": 50,
                    "particle_lifetime": 2.0,
                    "start_color": [1.0, 0.3, 0.0],
                    "end_color": [1.0, 0.0, 0.0],
                    "start_size": 0.2,
                    "end_size": 0.8,
                    "velocity": [0, 0, 2],
                    "velocity_variation": 0.5,
                    "gravity_scale": -0.2,
                    "air_resistance": 0.02,
                    "emitter_shape": "circle",
                    "emitter_radius": 0.3
                }
            },
            
            "浓密烟雾": {
                "metadata": {
                    "name": "浓密烟雾",
                    "description": "浓密的烟雾效果",
                    "author": "EG Team",
                    "version": "1.0",
                    "created": "2024-10-28",
                    "builtin": True
                },
                "config": {
                    "emitter_type": "smoke",
                    "emission_rate": 30,
                    "particle_lifetime": 4.0,
                    "start_color": [0.8, 0.8, 0.8],
                    "end_color": [0.3, 0.3, 0.3],
                    "start_size": 0.3,
                    "end_size": 1.5,
                    "velocity": [0, 0, 1],
                    "velocity_variation": 0.3,
                    "gravity_scale": -0.1,
                    "air_resistance": 0.05,
                    "emitter_shape": "circle",
                    "emitter_radius": 0.5
                }
            },
            
            "强力爆炸": {
                "metadata": {
                    "name": "强力爆炸",
                    "description": "强力的爆炸效果",
                    "author": "EG Team",
                    "version": "1.0",
                    "created": "2024-10-28",
                    "builtin": True
                },
                "config": {
                    "emitter_type": "explosion",
                    "emission_rate": 200,
                    "burst_count": 100,
                    "particle_lifetime": 1.5,
                    "start_color": [1.0, 0.8, 0.0],
                    "end_color": [1.0, 0.2, 0.0],
                    "start_size": 0.1,
                    "end_size": 0.5,
                    "velocity": [0, 0, 0],
                    "velocity_variation": 2.0,
                    "gravity_scale": 0.5,
                    "duration": 0.2,
                    "emitter_shape": "sphere",
                    "emitter_radius": 0.1
                }
            },
            
            "清澈水花": {
                "metadata": {
                    "name": "清澈水花",
                    "description": "清澈的水花效果",
                    "author": "EG Team",
                    "version": "1.0",
                    "created": "2024-10-28",
                    "builtin": True
                },
                "config": {
                    "emitter_type": "water",
                    "emission_rate": 80,
                    "particle_lifetime": 3.0,
                    "start_color": [0.2, 0.6, 1.0],
                    "end_color": [0.1, 0.3, 0.8],
                    "start_size": 0.1,
                    "end_size": 0.05,
                    "velocity": [0, 0, 3],
                    "velocity_variation": 1.0,
                    "gravity_scale": 2.0,
                    "bounce_factor": 0.3,
                    "air_resistance": 0.01,
                    "emitter_shape": "circle",
                    "emitter_radius": 0.2
                }
            },
            
            "魔法光球": {
                "metadata": {
                    "name": "魔法光球",
                    "description": "神秘的魔法光球效果",
                    "author": "EG Team",
                    "version": "1.0",
                    "created": "2024-10-28",
                    "builtin": True
                },
                "config": {
                    "emitter_type": "magic",
                    "emission_rate": 40,
                    "particle_lifetime": 3.0,
                    "start_color": [0.5, 0.2, 1.0],
                    "end_color": [0.8, 0.6, 1.0],
                    "start_size": 0.15,
                    "end_size": 0.05,
                    "velocity": [0, 0, 0.5],
                    "velocity_variation": 0.8,
                    "gravity_scale": -0.5,
                    "rotation_enabled": True,
                    "rotation_speed": 2.0,
                    "emitter_shape": "sphere",
                    "emitter_radius": 0.8
                }
            },
            
            "飘落雪花": {
                "metadata": {
                    "name": "飘落雪花",
                    "description": "冬季飘落的雪花效果",
                    "author": "EG Team",
                    "version": "1.0",
                    "created": "2024-10-28",
                    "builtin": True
                },
                "config": {
                    "emitter_type": "snow",
                    "emission_rate": 60,
                    "particle_lifetime": 8.0,
                    "start_color": [0.9, 0.9, 1.0],
                    "end_color": [0.9, 0.9, 1.0],
                    "start_size": 0.05,
                    "end_size": 0.05,
                    "velocity": [0, 0, -1],
                    "velocity_variation": 0.5,
                    "gravity_scale": 0.8,
                    "air_resistance": 0.1,
                    "bounce_factor": 0.2,
                    "emitter_shape": "box",
                    "emitter_dimensions": [20, 20, 1]
                }
            }
        }
        
    def save_preset(self, name: str, config: Dict[str, Any], 
                   description: str = "", author: str = "User") -> bool:
        """
        保存预设
        
        Args:
            name: 预设名称
            config: 预设配置
            description: 预设描述
            author: 作者
            
        Returns:
            是否保存成功
        """
        try:
            # 创建预设数据
            preset_data = {
                "metadata": {
                    "name": name,
                    "description": description,
                    "author": author,
                    "version": "1.0",
                    "created": datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
                    "builtin": False
                },
                "config": config
            }
            
            # 保存到文件
            filename = self._sanitize_filename(name) + ".json"
            filepath = os.path.join(self.presets_dir, filename)
            
            with open(filepath, 'w', encoding='utf-8') as f:
                json.dump(preset_data, f, indent=2, ensure_ascii=False, default=self._json_serializer)
                
            # 更新缓存
            self.presets_cache[name] = preset_data
            
            print(f"✓ 预设已保存: {name} -> {filepath}")
            return True
            
        except Exception as e:
            print(f"⚠ 预设保存失败 '{name}': {e}")
            return False
            
    def _json_serializer(self, obj):
        """JSON序列化器，处理特殊对象"""
        if isinstance(obj, Vec3):
            return [obj.x, obj.y, obj.z]
        raise TypeError(f"Object of type {type(obj)} is not JSON serializable")
            
    def load_preset(self, name: str) -> Optional[Dict[str, Any]]:
        """
        加载预设
        
        Args:
            name: 预设名称
            
        Returns:
            预设数据，如果不存在返回None
        """
        try:
            # 检查内置预设
            if name in self.builtin_presets:
                return self.builtin_presets[name]
                
            # 检查缓存
            if name in self.presets_cache and not self.cache_dirty:
                return self.presets_cache[name]
                
            # 从文件加载
            filename = self._sanitize_filename(name) + ".json"
            filepath = os.path.join(self.presets_dir, filename)
            
            if os.path.exists(filepath):
                with open(filepath, 'r', encoding='utf-8') as f:
                    preset_data = json.load(f)
                    
                # 更新缓存
                self.presets_cache[name] = preset_data
                self.cache_dirty = False
                
                print(f"✓ 预设已加载: {name}")
                return preset_data
            else:
                print(f"⚠ 预设文件不存在: {filepath}")
                return None
                
        except Exception as e:
            print(f"⚠ 预设加载失败 '{name}': {e}")
            return None
            
    def delete_preset(self, name: str) -> bool:
        """
        删除预设
        
        Args:
            name: 预设名称
            
        Returns:
            是否删除成功
        """
        try:
            # 不能删除内置预设
            if name in self.builtin_presets:
                print(f"⚠ 不能删除内置预设: {name}")
                return False
                
            # 删除文件
            filename = self._sanitize_filename(name) + ".json"
            filepath = os.path.join(self.presets_dir, filename)
            
            if os.path.exists(filepath):
                os.remove(filepath)
                
            # 从缓存移除
            if name in self.presets_cache:
                del self.presets_cache[name]
                
            print(f"✓ 预设已删除: {name}")
            return True
            
        except Exception as e:
            print(f"⚠ 预设删除失败 '{name}': {e}")
            return False
            
    def list_presets(self) -> List[str]:
        """
        获取所有预设名称列表
        
        Returns:
            预设名称列表
        """
        presets = []
        
        # 添加内置预设
        presets.extend(self.builtin_presets.keys())
        
        # 添加用户预设
        try:
            if os.path.exists(self.presets_dir):
                for filename in os.listdir(self.presets_dir):
                    if filename.endswith('.json'):
                        name = filename[:-5]  # 移除.json扩展名
                        # 尝试从文件名恢复原始名称
                        original_name = self._restore_filename(name)
                        if original_name not in presets:
                            presets.append(original_name)
                            
        except Exception as e:
            print(f"⚠ 列出预设失败: {e}")
            
        return sorted(presets)
        
    def get_preset_info(self, name: str) -> Optional[Dict[str, Any]]:
        """
        获取预设信息
        
        Args:
            name: 预设名称
            
        Returns:
            预设元数据
        """
        preset_data = self.load_preset(name)
        if preset_data and 'metadata' in preset_data:
            return preset_data['metadata']
        return None
        
    def get_preset_config(self, name: str) -> Optional[Dict[str, Any]]:
        """
        获取预设配置
        
        Args:
            name: 预设名称
            
        Returns:
            预设配置
        """
        preset_data = self.load_preset(name)
        if preset_data and 'config' in preset_data:
            return preset_data['config']
        return None
        
    def export_preset(self, name: str, filepath: str) -> bool:
        """
        导出预设到文件
        
        Args:
            name: 预设名称
            filepath: 导出文件路径
            
        Returns:
            是否导出成功
        """
        try:
            preset_data = self.load_preset(name)
            if not preset_data:
                print(f"⚠ 预设不存在: {name}")
                return False
                
            with open(filepath, 'w', encoding='utf-8') as f:
                json.dump(preset_data, f, indent=2, ensure_ascii=False, default=self._json_serializer)
                
            print(f"✓ 预设已导出: {name} -> {filepath}")
            return True
            
        except Exception as e:
            print(f"⚠ 预设导出失败 '{name}': {e}")
            return False
            
    def import_preset(self, filepath: str) -> bool:
        """
        从文件导入预设
        
        Args:
            filepath: 预设文件路径
            
        Returns:
            是否导入成功
        """
        try:
            if not os.path.exists(filepath):
                print(f"⚠ 预设文件不存在: {filepath}")
                return False
                
            with open(filepath, 'r', encoding='utf-8') as f:
                preset_data = json.load(f)
                
            # 验证预设数据格式
            if not self._validate_preset_data(preset_data):
                print(f"⚠ 预设文件格式无效: {filepath}")
                return False
                
            # 获取预设名称
            name = preset_data['metadata']['name']
            
            # 保存预设
            return self.save_preset(
                name,
                preset_data['config'],
                preset_data['metadata'].get('description', ''),
                preset_data['metadata'].get('author', 'Unknown')
            )
            
        except Exception as e:
            print(f"⚠ 预设导入失败: {e}")
            return False
            
    def _sanitize_filename(self, name: str) -> str:
        """清理文件名，移除非法字符"""
        import re
        # 移除或替换非法字符
        sanitized = re.sub(r'[<>:"/\\|?*]', '_', name)
        # 限制长度
        if len(sanitized) > 100:
            sanitized = sanitized[:100]
        return sanitized
        
    def _restore_filename(self, filename: str) -> str:
        """尝试恢复原始文件名"""
        # 简单实现：直接返回文件名
        # 实际应用中可能需要更复杂的映射
        return filename
        
    def _validate_preset_data(self, data: Dict) -> bool:
        """验证预设数据格式"""
        try:
            # 检查必需字段
            if 'metadata' not in data or 'config' not in data:
                return False
                
            metadata = data['metadata']
            if 'name' not in metadata:
                return False
                
            # 基本验证通过
            return True
            
        except:
            return False
            
    def clear_cache(self):
        """清空预设缓存"""
        self.presets_cache.clear()
        self.cache_dirty = True
        print("✓ 预设缓存已清空")
        
    def get_cache_stats(self) -> Dict[str, Any]:
        """获取缓存统计信息"""
        return {
            'cached_presets': len(self.presets_cache),
            'builtin_presets': len(self.builtin_presets),
            'cache_dirty': self.cache_dirty
        }
        
    def refresh_presets(self):
        """刷新预设列表"""
        self.cache_dirty = True
        print("✓ 预设列表已刷新")
        
    def create_preset_from_config(self, name: str, config: Dict[str, Any], 
                                 description: str = "", author: str = "User") -> bool:
        """
        从配置创建预设
        
        Args:
            name: 预设名称
            config: 预设配置
            description: 预设描述
            author: 作者
            
        Returns:
            是否创建成功
        """
        return self.save_preset(name, config, description, author)
        
    def duplicate_preset(self, source_name: str, new_name: str) -> bool:
        """
        复制预设
        
        Args:
            source_name: 源预设名称
            new_name: 新预设名称
            
        Returns:
            是否复制成功
        """
        preset_data = self.load_preset(source_name)
        if not preset_data:
            print(f"⚠ 源预设不存在: {source_name}")
            return False
            
        # 更新元数据
        preset_data['metadata']['name'] = new_name
        preset_data['metadata']['created'] = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        preset_data['metadata']['builtin'] = False
        
        return self.save_preset(
            new_name,
            preset_data['config'],
            preset_data['metadata'].get('description', ''),
            preset_data['metadata'].get('author', 'User')
        )
        
    def update_preset_description(self, name: str, description: str) -> bool:
        """
        更新预设描述
        
        Args:
            name: 预设名称
            description: 新描述
            
        Returns:
            是否更新成功
        """
        preset_data = self.load_preset(name)
        if not preset_data:
            print(f"⚠ 预设不存在: {name}")
            return False
            
        if preset_data['metadata'].get('builtin', False):
            print(f"⚠ 不能修改内置预设: {name}")
            return False
            
        preset_data['metadata']['description'] = description
        
        return self.save_preset(
            name,
            preset_data['config'],
            description,
            preset_data['metadata'].get('author', 'User')
        )
        
    def search_presets(self, keyword: str) -> List[str]:
        """
        搜索预设
        
        Args:
            keyword: 搜索关键词
            
        Returns:
            匹配的预设名称列表
        """
        all_presets = self.list_presets()
        keyword = keyword.lower()
        
        matching_presets = []
        for preset_name in all_presets:
            # 检查名称和描述
            if keyword in preset_name.lower():
                matching_presets.append(preset_name)
            else:
                info = self.get_preset_info(preset_name)
                if info and keyword in info.get('description', '').lower():
                    matching_presets.append(preset_name)
                    
        return matching_presets

