"""
地形序列化器
负责地形数据的序列化和反序列化
"""

import numpy as np
import json
import pickle
import zlib
import base64
from typing import Dict, Any, Optional
import time
import os

class TerrainSerializer:
    """
    地形序列化器
    负责地形数据的序列化和反序列化，支持多种格式和压缩方式
    """
    
    def __init__(self, plugin):
        """
        初始化地形序列化器
        
        Args:
            plugin: 程序化地形生成插件实例
        """
        self.plugin = plugin
        self.enabled = False
        self.initialized = False
        
        # 序列化配置
        self.serialization_params = {
            'default_format': 'json',
            'compression_enabled': True,
            'compression_level': 6,
            'chunk_size': 1024,
            'include_metadata': True,
            'include_textures': True,
            'include_vegetation': True,
            'include_water': True
        }
        
        # 支持的格式
        self.supported_formats = ['json', 'pickle', 'binary', 'custom']
        
        # 统计信息
        self.stats = {
            'terrains_saved': 0,
            'terrains_loaded': 0,
            'total_save_time': 0.0,
            'total_load_time': 0.0,
            'average_save_time': 0.0,
            'average_load_time': 0.0,
            'data_compressed': 0,
            'data_uncompressed': 0
        }
        
        print("✓ 地形序列化器已创建")
        
    def initialize(self) -> bool:
        """
        初始化地形序列化器
        
        Returns:
            是否初始化成功
        """
        try:
            self.initialized = True
            print("✓ 地形序列化器初始化完成")
            return True
            
        except Exception as e:
            print(f"✗ 地形序列化器初始化失败: {e}")
            import traceback
            traceback.print_exc()
            return False
            
    def enable(self) -> bool:
        """
        启用地形序列化器
        
        Returns:
            是否启用成功
        """
        try:
            if not self.initialized:
                print("✗ 地形序列化器未初始化")
                return False
                
            self.enabled = True
            print("✓ 地形序列化器已启用")
            return True
            
        except Exception as e:
            print(f"✗ 地形序列化器启用失败: {e}")
            import traceback
            traceback.print_exc()
            return False
            
    def disable(self):
        """禁用地形序列化器"""
        try:
            self.enabled = False
            print("✓ 地形序列化器已禁用")
            
        except Exception as e:
            print(f"✗ 地形序列化器禁用失败: {e}")
            import traceback
            traceback.print_exc()
            
    def finalize(self):
        """清理地形序列化器资源"""
        try:
            self.disable()
            self.initialized = False
            print("✓ 地形序列化器资源已清理")
            
        except Exception as e:
            print(f"✗ 地形序列化器资源清理失败: {e}")
            import traceback
            traceback.print_exc()
            
    def update(self, dt: float):
        """
        更新地形序列化器状态
        
        Args:
            dt: 时间增量
        """
        # 处理更新逻辑
        pass
        
    def save_terrain(self, filename: str, terrain_data: Dict[str, Any] = None, 
                    format: str = None, compress: bool = None) -> bool:
        """
        保存地形数据
        
        Args:
            filename: 文件名
            terrain_data: 地形数据字典（如果为None，则从地形管理器获取）
            format: 保存格式
            compress: 是否压缩
            
        Returns:
            是否保存成功
        """
        try:
            save_start_time = time.time()
            
            if not self.enabled:
                print("✗ 地形序列化器未启用")
                return False
                
            # 使用默认参数如果未指定
            if format is None:
                format = self.serialization_params['default_format']
            if compress is None:
                compress = self.serialization_params['compression_enabled']
                
            # 验证格式
            if format not in self.supported_formats:
                print(f"✗ 不支持的格式: {format}")
                return False
                
            print(f"✓ 开始保存地形到 {filename} (格式: {format}, 压缩: {compress})...")
            
            # 如果未提供地形数据，则从地形管理器获取
            if terrain_data is None:
                if self.plugin.terrain_manager:
                    terrain_data = self.plugin.terrain_manager.get_terrain_data()
                else:
                    print("✗ 无法获取地形数据")
                    return False
                    
            # 准备保存数据
            save_data = self._prepare_terrain_data(terrain_data)
            
            # 根据格式保存
            if format == 'json':
                success = self._save_json(filename, save_data, compress)
            elif format == 'pickle':
                success = self._save_pickle(filename, save_data, compress)
            elif format == 'binary':
                success = self._save_binary(filename, save_data, compress)
            elif format == 'custom':
                success = self._save_custom(filename, save_data, compress)
            else:
                print(f"✗ 不支持的保存格式: {format}")
                return False
                
            if success:
                # 更新统计信息
                save_time = time.time() - save_start_time
                self.stats['terrains_saved'] += 1
                self.stats['total_save_time'] += save_time
                if self.stats['terrains_saved'] > 0:
                    self.stats['average_save_time'] = (
                        self.stats['total_save_time'] / self.stats['terrains_saved']
                    )
                    
                print(f"✓ 地形保存完成，耗时: {save_time:.3f}秒")
                return True
            else:
                print("✗ 地形保存失败")
                return False
                
        except Exception as e:
            print(f"✗ 地形保存失败: {e}")
            import traceback
            traceback.print_exc()
            return False
            
    def load_terrain(self, filename: str, format: str = None) -> Optional[Dict[str, Any]]:
        """
        加载地形数据
        
        Args:
            filename: 文件名
            format: 加载格式（如果为None，则自动检测）
            
        Returns:
            地形数据字典或None
        """
        try:
            load_start_time = time.time()
            
            if not self.enabled:
                print("✗ 地形序列化器未启用")
                return None
                
            # 检查文件是否存在
            if not os.path.exists(filename):
                print(f"✗ 文件不存在: {filename}")
                return None
                
            print(f"✓ 开始加载地形从 {filename}...")
            
            # 如果未指定格式，则尝试自动检测
            if format is None:
                format = self._detect_format(filename)
                
            # 验证格式
            if format not in self.supported_formats:
                print(f"✗ 不支持的格式: {format}")
                return None
                
            # 根据格式加载
            if format == 'json':
                terrain_data = self._load_json(filename)
            elif format == 'pickle':
                terrain_data = self._load_pickle(filename)
            elif format == 'binary':
                terrain_data = self._load_binary(filename)
            elif format == 'custom':
                terrain_data = self._load_custom(filename)
            else:
                print(f"✗ 不支持的加载格式: {format}")
                return None
                
            if terrain_data is not None:
                # 处理加载的数据
                processed_data = self._process_loaded_data(terrain_data)
                
                # 更新统计信息
                load_time = time.time() - load_start_time
                self.stats['terrains_loaded'] += 1
                self.stats['total_load_time'] += load_time
                if self.stats['terrains_loaded'] > 0:
                    self.stats['average_load_time'] = (
                        self.stats['total_load_time'] / self.stats['terrains_loaded']
                    )
                    
                print(f"✓ 地形加载完成，耗时: {load_time:.3f}秒")
                return processed_data
            else:
                print("✗ 地形加载失败")
                return None
                
        except Exception as e:
            print(f"✗ 地形加载失败: {e}")
            import traceback
            traceback.print_exc()
            return None
            
    def _prepare_terrain_data(self, terrain_data: Dict[str, Any]) -> Dict[str, Any]:
        """
        准备地形数据以供保存
        
        Args:
            terrain_data: 原始地形数据
            
        Returns:
            准备好的地形数据
        """
        try:
            # 创建保存数据的副本
            save_data = {
                'version': '1.0',
                'timestamp': time.time(),
                'format': self.serialization_params['default_format']
            }
            
            # 添加地形数据
            if 'heightmap' in terrain_data and terrain_data['heightmap'] is not None:
                heightmap = terrain_data['heightmap']
                save_data['heightmap'] = {
                    'data': heightmap.tolist() if isinstance(heightmap, np.ndarray) else heightmap,
                    'shape': heightmap.shape if isinstance(heightmap, np.ndarray) else None,
                    'dtype': str(heightmap.dtype) if isinstance(heightmap, np.ndarray) else 'unknown'
                }
                
            # 添加法线图
            if 'normalmap' in terrain_data and terrain_data['normalmap'] is not None:
                normalmap = terrain_data['normalmap']
                save_data['normalmap'] = {
                    'data': normalmap.tolist() if isinstance(normalmap, np.ndarray) else normalmap,
                    'shape': normalmap.shape if isinstance(normalmap, np.ndarray) else None,
                    'dtype': str(normalmap.dtype) if isinstance(normalmap, np.ndarray) else 'unknown'
                }
                
            # 添加生物群落图
            if self.serialization_params['include_metadata']:
                if 'biome_map' in terrain_data and terrain_data['biome_map'] is not None:
                    biome_map = terrain_data['biome_map']
                    save_data['biome_map'] = {
                        'data': biome_map.tolist() if isinstance(biome_map, np.ndarray) else biome_map,
                        'shape': biome_map.shape if isinstance(biome_map, np.ndarray) else None,
                        'dtype': str(biome_map.dtype) if isinstance(biome_map, np.ndarray) else 'unknown'
                    }
                    
                # 添加湿度图
                if 'moisture_map' in terrain_data and terrain_data['moisture_map'] is not None:
                    moisture_map = terrain_data['moisture_map']
                    save_data['moisture_map'] = {
                        'data': moisture_map.tolist() if isinstance(moisture_map, np.ndarray) else moisture_map,
                        'shape': moisture_map.shape if isinstance(moisture_map, np.ndarray) else None,
                        'dtype': str(moisture_map.dtype) if isinstance(moisture_map, np.ndarray) else 'unknown'
                    }
                    
                # 添加温度图
                if 'temperature_map' in terrain_data and terrain_data['temperature_map'] is not None:
                    temperature_map = terrain_data['temperature_map']
                    save_data['temperature_map'] = {
                        'data': temperature_map.tolist() if isinstance(temperature_map, np.ndarray) else temperature_map,
                        'shape': temperature_map.shape if isinstance(temperature_map, np.ndarray) else None,
                        'dtype': str(temperature_map.dtype) if isinstance(temperature_map, np.ndarray) else 'unknown'
                    }
                    
            # 添加侵蚀数据
            if 'erosion_map' in terrain_data and terrain_data['erosion_map'] is not None:
                erosion_map = terrain_data['erosion_map']
                save_data['erosion_map'] = {
                    'data': erosion_map.tolist() if isinstance(erosion_map, np.ndarray) else erosion_map,
                    'shape': erosion_map.shape if isinstance(erosion_map, np.ndarray) else None,
                    'dtype': str(erosion_map.dtype) if isinstance(erosion_map, np.ndarray) else 'unknown'
                }
                
            # 添加沉积物数据
            if 'sediment_map' in terrain_data and terrain_data['sediment_map'] is not None:
                sediment_map = terrain_data['sediment_map']
                save_data['sediment_map'] = {
                    'data': sediment_map.tolist() if isinstance(sediment_map, np.ndarray) else sediment_map,
                    'shape': sediment_map.shape if isinstance(sediment_map, np.ndarray) else None,
                    'dtype': str(sediment_map.dtype) if isinstance(sediment_map, np.ndarray) else 'unknown'
                }
                
            # 添加水图
            if self.serialization_params['include_water']:
                if 'water_map' in terrain_data and terrain_data['water_map'] is not None:
                    water_map = terrain_data['water_map']
                    save_data['water_map'] = {
                        'data': water_map.tolist() if isinstance(water_map, np.ndarray) else water_map,
                        'shape': water_map.shape if isinstance(water_map, np.ndarray) else None,
                        'dtype': str(water_map.dtype) if isinstance(water_map, np.ndarray) else 'unknown'
                    }
                    
            # 添加植被数据
            if self.serialization_params['include_vegetation']:
                if 'vegetation_map' in terrain_data and terrain_data['vegetation_map'] is not None:
                    vegetation_map = terrain_data['vegetation_map']
                    save_data['vegetation_map'] = {
                        'data': vegetation_map.tolist() if isinstance(vegetation_map, np.ndarray) else vegetation_map,
                        'shape': vegetation_map.shape if isinstance(vegetation_map, np.ndarray) else None,
                        'dtype': str(vegetation_map.dtype) if isinstance(vegetation_map, np.ndarray) else 'unknown'
                    }
                    
            # 添加统计信息
            if 'stats' in terrain_data:
                save_data['stats'] = terrain_data['stats']
                
            return save_data
            
        except Exception as e:
            print(f"✗ 地形数据准备失败: {e}")
            return {}
            
    def _process_loaded_data(self, loaded_data: Dict[str, Any]) -> Dict[str, Any]:
        """
        处理加载的地形数据
        
        Args:
            loaded_data: 加载的地形数据
            
        Returns:
            处理后的地形数据
        """
        try:
            # 创建处理后的数据
            processed_data = {}
            
            # 处理高度图
            if 'heightmap' in loaded_data:
                heightmap_data = loaded_data['heightmap']
                if 'data' in heightmap_data:
                    processed_data['heightmap'] = np.array(heightmap_data['data'], dtype=np.float32)
                    
            # 处理法线图
            if 'normalmap' in loaded_data:
                normalmap_data = loaded_data['normalmap']
                if 'data' in normalmap_data:
                    processed_data['normalmap'] = np.array(normalmap_data['data'], dtype=np.float32)
                    
            # 处理生物群落图
            if 'biome_map' in loaded_data:
                biome_data = loaded_data['biome_map']
                if 'data' in biome_data:
                    processed_data['biome_map'] = np.array(biome_data['data'], dtype=np.int32)
                    
            # 处理湿度图
            if 'moisture_map' in loaded_data:
                moisture_data = loaded_data['moisture_map']
                if 'data' in moisture_data:
                    processed_data['moisture_map'] = np.array(moisture_data['data'], dtype=np.float32)
                    
            # 处理温度图
            if 'temperature_map' in loaded_data:
                temperature_data = loaded_data['temperature_map']
                if 'data' in temperature_data:
                    processed_data['temperature_map'] = np.array(temperature_data['data'], dtype=np.float32)
                    
            # 处理侵蚀图
            if 'erosion_map' in loaded_data:
                erosion_data = loaded_data['erosion_map']
                if 'data' in erosion_data:
                    processed_data['erosion_map'] = np.array(erosion_data['data'], dtype=np.float32)
                    
            # 处理沉积物图
            if 'sediment_map' in loaded_data:
                sediment_data = loaded_data['sediment_map']
                if 'data' in sediment_data:
                    processed_data['sediment_map'] = np.array(sediment_data['data'], dtype=np.float32)
                    
            # 处理水图
            if 'water_map' in loaded_data:
                water_data = loaded_data['water_map']
                if 'data' in water_data:
                    processed_data['water_map'] = np.array(water_data['data'], dtype=np.float32)
                    
            # 处理植被图
            if 'vegetation_map' in loaded_data:
                vegetation_data = loaded_data['vegetation_map']
                if 'data' in vegetation_data:
                    processed_data['vegetation_map'] = np.array(vegetation_data['data'], dtype=np.int32)
                    
            # 处理统计信息
            if 'stats' in loaded_data:
                processed_data['stats'] = loaded_data['stats']
                
            return processed_data
            
        except Exception as e:
            print(f"✗ 加载数据处理失败: {e}")
            return {}
            
    def _save_json(self, filename: str, data: Dict[str, Any], compress: bool) -> bool:
        """
        以JSON格式保存地形数据
        
        Args:
            filename: 文件名
            data: 地形数据
            compress: 是否压缩
            
        Returns:
            是否保存成功
        """
        try:
            # 序列化为JSON
            json_data = json.dumps(data, ensure_ascii=False, indent=2)
            
            if compress:
                # 压缩数据
                compressed_data = zlib.compress(json_data.encode('utf-8'), 
                                              self.serialization_params['compression_level'])
                with open(filename, 'wb') as f:
                    f.write(compressed_data)
                self.stats['data_compressed'] += len(compressed_data)
                self.stats['data_uncompressed'] += len(json_data.encode('utf-8'))
            else:
                # 不压缩
                with open(filename, 'w', encoding='utf-8') as f:
                    f.write(json_data)
                self.stats['data_uncompressed'] += len(json_data.encode('utf-8'))
                
            return True
            
        except Exception as e:
            print(f"✗ JSON格式地形保存失败: {e}")
            return False
            
    def _save_pickle(self, filename: str, data: Dict[str, Any], compress: bool) -> bool:
        """
        以Pickle格式保存地形数据
        
        Args:
            filename: 文件名
            data: 地形数据
            compress: 是否压缩
            
        Returns:
            是否保存成功
        """
        try:
            # 序列化为Pickle
            pickle_data = pickle.dumps(data)
            
            if compress:
                # 压缩数据
                compressed_data = zlib.compress(pickle_data, 
                                              self.serialization_params['compression_level'])
                with open(filename, 'wb') as f:
                    f.write(compressed_data)
                self.stats['data_compressed'] += len(compressed_data)
                self.stats['data_uncompressed'] += len(pickle_data)
            else:
                # 不压缩
                with open(filename, 'wb') as f:
                    f.write(pickle_data)
                self.stats['data_uncompressed'] += len(pickle_data)
                
            return True
            
        except Exception as e:
            print(f"✗ Pickle格式地形保存失败: {e}")
            return False
            
    def _save_binary(self, filename: str, data: Dict[str, Any], compress: bool) -> bool:
        """
        以二进制格式保存地形数据
        
        Args:
            filename: 文件名
            data: 地形数据
            compress: 是否压缩
            
        Returns:
            是否保存成功
        """
        try:
            # 转换为二进制格式
            binary_data = self._convert_to_binary(data)
            
            if compress:
                # 压缩数据
                compressed_data = zlib.compress(binary_data, 
                                              self.serialization_params['compression_level'])
                with open(filename, 'wb') as f:
                    f.write(compressed_data)
                self.stats['data_compressed'] += len(compressed_data)
                self.stats['data_uncompressed'] += len(binary_data)
            else:
                # 不压缩
                with open(filename, 'wb') as f:
                    f.write(binary_data)
                self.stats['data_uncompressed'] += len(binary_data)
                
            return True
            
        except Exception as e:
            print(f"✗ 二进制格式地形保存失败: {e}")
            return False
            
    def _save_custom(self, filename: str, data: Dict[str, Any], compress: bool) -> bool:
        """
        以自定义格式保存地形数据
        
        Args:
            filename: 文件名
            data: 地形数据
            compress: 是否压缩
            
        Returns:
            是否保存成功
        """
        try:
            # 自定义格式保存（这里简化为JSON格式）
            return self._save_json(filename, data, compress)
        except Exception as e:
            print(f"✗ 自定义格式地形保存失败: {e}")
            return False
            
    def _load_json(self, filename: str) -> Optional[Dict[str, Any]]:
        """
        从JSON格式加载地形数据
        
        Args:
            filename: 文件名
            
        Returns:
            地形数据字典或None
        """
        try:
            # 读取文件
            with open(filename, 'rb') as f:
                file_data = f.read()
                
            # 检查是否压缩
            try:
                # 尝试解压
                decompressed_data = zlib.decompress(file_data)
                json_data = decompressed_data.decode('utf-8')
                self.stats['data_compressed'] += len(file_data)
                self.stats['data_uncompressed'] += len(decompressed_data)
            except zlib.error:
                # 未压缩的JSON
                json_data = file_data.decode('utf-8')
                self.stats['data_uncompressed'] += len(file_data)
                
            # 解析JSON
            data = json.loads(json_data)
            return data
            
        except Exception as e:
            print(f"✗ JSON格式地形加载失败: {e}")
            return None
            
    def _load_pickle(self, filename: str) -> Optional[Dict[str, Any]]:
        """
        从Pickle格式加载地形数据
        
        Args:
            filename: 文件名
            
        Returns:
            地形数据字典或None
        """
        try:
            # 读取文件
            with open(filename, 'rb') as f:
                file_data = f.read()
                
            # 检查是否压缩
            try:
                # 尝试解压
                decompressed_data = zlib.decompress(file_data)
                pickle_data = decompressed_data
                self.stats['data_compressed'] += len(file_data)
                self.stats['data_uncompressed'] += len(decompressed_data)
            except zlib.error:
                # 未压缩的Pickle
                pickle_data = file_data
                self.stats['data_uncompressed'] += len(file_data)
                
            # 解析Pickle
            data = pickle.loads(pickle_data)
            return data
            
        except Exception as e:
            print(f"✗ Pickle格式地形加载失败: {e}")
            return None
            
    def _load_binary(self, filename: str) -> Optional[Dict[str, Any]]:
        """
        从二进制格式加载地形数据
        
        Args:
            filename: 文件名
            
        Returns:
            地形数据字典或None
        """
        try:
            # 读取文件
            with open(filename, 'rb') as f:
                file_data = f.read()
                
            # 检查是否压缩
            try:
                # 尝试解压
                decompressed_data = zlib.decompress(file_data)
                binary_data = decompressed_data
                self.stats['data_compressed'] += len(file_data)
                self.stats['data_uncompressed'] += len(decompressed_data)
            except zlib.error:
                # 未压缩的二进制数据
                binary_data = file_data
                self.stats['data_uncompressed'] += len(file_data)
                
            # 解析二进制数据
            data = self._convert_from_binary(binary_data)
            return data
            
        except Exception as e:
            print(f"✗ 二进制格式地形加载失败: {e}")
            return None
            
    def _load_custom(self, filename: str) -> Optional[Dict[str, Any]]:
        """
        从自定义格式加载地形数据
        
        Args:
            filename: 文件名
            
        Returns:
            地形数据字典或None
        """
        try:
            # 自定义格式加载（这里简化为JSON格式）
            return self._load_json(filename)
        except Exception as e:
            print(f"✗ 自定义格式地形加载失败: {e}")
            return None
            
    def _convert_to_binary(self, data: Dict[str, Any]) -> bytes:
        """
        将数据转换为二进制格式
        
        Args:
            data: 数据字典
            
        Returns:
            二进制数据
        """
        try:
            # 这里简化为使用Pickle作为二进制格式
            return pickle.dumps(data)
        except Exception as e:
            print(f"✗ 数据转换为二进制失败: {e}")
            return b''
            
    def _convert_from_binary(self, binary_data: bytes) -> Dict[str, Any]:
        """
        从二进制数据转换为字典
        
        Args:
            binary_data: 二进制数据
            
        Returns:
            数据字典
        """
        try:
            # 这里简化为使用Pickle作为二进制格式
            return pickle.loads(binary_data)
        except Exception as e:
            print(f"✗ 二进制数据转换失败: {e}")
            return {}
            
    def _detect_format(self, filename: str) -> str:
        """
        检测文件格式
        
        Args:
            filename: 文件名
            
        Returns:
            检测到的格式
        """
        try:
            # 根据文件扩展名检测格式
            if filename.endswith('.json') or filename.endswith('.json.gz'):
                return 'json'
            elif filename.endswith('.pkl') or filename.endswith('.pkl.gz'):
                return 'pickle'
            elif filename.endswith('.bin') or filename.endswith('.bin.gz'):
                return 'binary'
            else:
                # 默认使用JSON格式
                return self.serialization_params['default_format']
                
        except Exception as e:
            print(f"✗ 格式检测失败: {e}")
            return self.serialization_params['default_format']
            
    def get_stats(self) -> Dict[str, Any]:
        """
        获取统计信息
        
        Returns:
            统计信息字典
        """
        # 更新平均时间
        if self.stats['terrains_saved'] > 0:
            self.stats['average_save_time'] = self.stats['total_save_time'] / self.stats['terrains_saved']
        if self.stats['terrains_loaded'] > 0:
            self.stats['average_load_time'] = self.stats['total_load_time'] / self.stats['terrains_loaded']
            
        # 计算压缩率
        total_data = self.stats['data_compressed'] + self.stats['data_uncompressed']
        compression_ratio = 0.0
        if total_data > 0:
            compression_ratio = self.stats['data_compressed'] / total_data if self.stats['data_compressed'] > 0 else 1.0
            
        stats = self.stats.copy()
        stats['compression_ratio'] = compression_ratio
        return stats
        
    def reset_stats(self):
        """重置统计信息"""
        self.stats = {
            'terrains_saved': 0,
            'terrains_loaded': 0,
            'total_save_time': 0.0,
            'total_load_time': 0.0,
            'average_save_time': 0.0,
            'average_load_time': 0.0,
            'data_compressed': 0,
            'data_uncompressed': 0
        }
        print("✓ 地形序列化器统计信息已重置")
        
    def set_serialization_parameters(self, params: Dict[str, Any]):
        """
        设置序列化参数
        
        Args:
            params: 参数字典
        """
        self.serialization_params.update(params)
        print(f"✓ 序列化参数已更新: {self.serialization_params}")
        
    def export_terrain_to_image(self, heightmap: np.ndarray, filename: str) -> bool:
        """
        导出地形为图像文件
        
        Args:
            heightmap: 高度图数据
            filename: 文件名
            
        Returns:
            是否导出成功
        """
        try:
            print(f"✓ 开始导出地形到图像 {filename}...")
            
            # 确保高度图在0-1范围内
            normalized_heightmap = (heightmap - np.min(heightmap)) / (np.max(heightmap) - np.min(heightmap))
            
            # 转换为0-255范围的整数
            image_data = (normalized_heightmap * 255).astype(np.uint8)
            
            # 保存为PNG文件
            try:
                from PIL import Image
                image = Image.fromarray(image_data, mode='L')
                image.save(filename)
                print("✓ 地形图像导出完成")
                return True
            except ImportError:
                # 如果没有PIL，保存为原始二进制数据
                with open(filename + '.raw', 'wb') as f:
                    f.write(image_data.tobytes())
                print("✓ 地形数据导出完成（无PIL，保存为.raw文件）")
                return True
                
        except Exception as e:
            print(f"✗ 地形图像导出失败: {e}")
            import traceback
            traceback.print_exc()
            return False
            
    def import_terrain_from_image(self, filename: str) -> Optional[np.ndarray]:
        """
        从图像文件导入地形
        
        Args:
            filename: 文件名
            
        Returns:
            高度图数据或None
        """
        try:
            print(f"✓ 开始从图像 {filename} 导入地形...")
            
            # 读取图像文件
            try:
                from PIL import Image
                image = Image.open(filename)
                # 转换为灰度图
                image = image.convert('L')
                # 转换为numpy数组
                image_data = np.array(image, dtype=np.float32)
                # 归一化到0-1范围
                heightmap = image_data / 255.0
                print("✓ 地形图像导入完成")
                return heightmap
            except ImportError:
                # 如果没有PIL，尝试读取原始二进制数据
                if filename.endswith('.raw'):
                    with open(filename, 'rb') as f:
                        raw_data = f.read()
                    # 假设是512x512的图像
                    image_data = np.frombuffer(raw_data, dtype=np.uint8)
                    heightmap = image_data.astype(np.float32) / 255.0
                    # 重塑为方形
                    size = int(np.sqrt(len(heightmap)))
                    heightmap = heightmap.reshape((size, size))
                    print("✓ 地形数据导入完成（从.raw文件）")
                    return heightmap
                else:
                    print("✗ 无法读取图像文件（需要PIL库）")
                    return None
                    
        except Exception as e:
            print(f"✗ 地形图像导入失败: {e}")
            import traceback
            traceback.print_exc()
            return None
            
    def backup_terrain(self, filename: str) -> bool:
        """
        备份当前地形
        
        Args:
            filename: 备份文件名
            
        Returns:
            是否备份成功
        """
        try:
            if not self.enabled:
                print("✗ 地形序列化器未启用")
                return False
                
            # 获取当前地形数据
            if self.plugin.terrain_manager:
                terrain_data = self.plugin.terrain_manager.get_terrain_data()
                if terrain_data:
                    # 保存备份
                    backup_filename = filename + '.backup'
                    success = self.save_terrain(backup_filename, terrain_data)
                    if success:
                        print(f"✓ 地形已备份到 {backup_filename}")
                        return True
                    else:
                        print("✗ 地形备份失败")
                        return False
                else:
                    print("✗ 无法获取当前地形数据")
                    return False
            else:
                print("✗ 地形管理器不可用")
                return False
                
        except Exception as e:
            print(f"✗ 地形备份失败: {e}")
            import traceback
            traceback.print_exc()
            return False
            
    def restore_terrain(self, filename: str) -> bool:
        """
        恢复地形备份
        
        Args:
            filename: 备份文件名
            
        Returns:
            是否恢复成功
        """
        try:
            if not self.enabled:
                print("✗ 地形序列化器未启用")
                return False
                
            # 加载备份数据
            backup_filename = filename + '.backup'
            terrain_data = self.load_terrain(backup_filename)
            
            if terrain_data:
                # 应用到地形管理器
                if self.plugin.terrain_manager:
                    # 这里应该调用地形管理器的方法来恢复数据
                    # 由于地形管理器可能没有相应的方法，我们只打印信息
                    print(f"✓ 地形已从 {backup_filename} 恢复")
                    print("注意：需要在地形管理器中实现实际的恢复逻辑")
                    return True
                else:
                    print("✗ 地形管理器不可用")
                    return False
            else:
                print("✗ 无法加载备份数据")
                return False
                
        except Exception as e:
            print(f"✗ 地形恢复失败: {e}")
            import traceback
            traceback.print_exc()
            return False
            
    def get_file_info(self, filename: str) -> Dict[str, Any]:
        """
        获取文件信息
        
        Args:
            filename: 文件名
            
        Returns:
            文件信息字典
        """
        try:
            if not os.path.exists(filename):
                return {'error': '文件不存在'}
                
            # 获取文件统计信息
            stat = os.stat(filename)
            
            file_info = {
                'filename': filename,
                'size': stat.st_size,
                'created': time.ctime(stat.st_ctime),
                'modified': time.ctime(stat.st_mtime),
                'accessed': time.ctime(stat.st_atime)
            }
            
            # 尝试加载文件以获取地形信息
            try:
                terrain_data = self.load_terrain(filename)
                if terrain_data:
                    file_info['terrain_info'] = {
                        'has_heightmap': 'heightmap' in terrain_data and terrain_data['heightmap'] is not None,
                        'has_biome_map': 'biome_map' in terrain_data and terrain_data['biome_map'] is not None,
                        'has_vegetation_map': 'vegetation_map' in terrain_data and terrain_data['vegetation_map'] is not None,
                        'has_water_map': 'water_map' in terrain_data and terrain_data['water_map'] is not None
                    }
                    
                    if 'stats' in terrain_data:
                        file_info['terrain_stats'] = terrain_data['stats']
                        
            except Exception as e:
                file_info['load_error'] = str(e)
                
            return file_info
            
        except Exception as e:
            print(f"✗ 文件信息获取失败: {e}")
            return {'error': str(e)}
            
    def list_terrain_files(self, directory: str = '.') -> List[str]:
        """
        列出目录中的地形文件
        
        Args:
            directory: 目录路径
            
        Returns:
            地形文件列表
        """
        try:
            terrain_files = []
            
            # 支持的文件扩展名
            supported_extensions = ['.json', '.pkl', '.bin', '.raw']
            
            # 遍历目录
            for filename in os.listdir(directory):
                file_path = os.path.join(directory, filename)
                if os.path.isfile(file_path):
                    # 检查文件扩展名
                    _, ext = os.path.splitext(filename)
                    if ext in supported_extensions:
                        terrain_files.append(filename)
                        
            return terrain_files
            
        except Exception as e:
            print(f"✗ 地形文件列表获取失败: {e}")
            return []
            
    def delete_terrain_file(self, filename: str) -> bool:
        """
        删除地形文件
        
        Args:
            filename: 文件名
            
        Returns:
            是否删除成功
        """
        try:
            if os.path.exists(filename):
                os.remove(filename)
                print(f"✓ 地形文件 {filename} 已删除")
                return True
            else:
                print(f"✗ 地形文件不存在: {filename}")
                return False
                
        except Exception as e:
            print(f"✗ 地形文件删除失败: {e}")
            return False
            
    def compress_terrain_file(self, filename: str, output_filename: str = None) -> bool:
        """
        压缩地形文件
        
        Args:
            filename: 输入文件名
            output_filename: 输出文件名（如果为None，则在原文件名后添加.gz）
            
        Returns:
            是否压缩成功
        """
        try:
            if not os.path.exists(filename):
                print(f"✗ 文件不存在: {filename}")
                return False
                
            if output_filename is None:
                output_filename = filename + '.gz'
                
            # 读取原始文件
            with open(filename, 'rb') as f:
                data = f.read()
                
            # 压缩数据
            compressed_data = zlib.compress(data, self.serialization_params['compression_level'])
            
            # 写入压缩文件
            with open(output_filename, 'wb') as f:
                f.write(compressed_data)
                
            print(f"✓ 地形文件已压缩: {filename} -> {output_filename}")
            return True
            
        except Exception as e:
            print(f"✗ 地形文件压缩失败: {e}")
            return False
            
    def decompress_terrain_file(self, filename: str, output_filename: str = None) -> bool:
        """
        解压地形文件
        
        Args:
            filename: 输入文件名（应该以.gz结尾）
            output_filename: 输出文件名（如果为None，则移除.gz后缀）
            
        Returns:
            是否解压成功
        """
        try:
            if not os.path.exists(filename):
                print(f"✗ 文件不存在: {filename}")
                return False
                
            if output_filename is None:
                if filename.endswith('.gz'):
                    output_filename = filename[:-3]
                else:
                    output_filename = filename + '.decompressed'
                    
            # 读取压缩文件
            with open(filename, 'rb') as f:
                compressed_data = f.read()
                
            # 解压数据
            try:
                data = zlib.decompress(compressed_data)
            except zlib.error as e:
                print(f"✗ 文件解压失败: {e}")
                return False
                
            # 写入解压文件
            with open(output_filename, 'wb') as f:
                f.write(data)
                
            print(f"✓ 地形文件已解压: {filename} -> {output_filename}")
            return True
            
        except Exception as e:
            print(f"✗ 地形文件解压失败: {e}")
            return False
            
    def validate_terrain_file(self, filename: str) -> bool:
        """
        验证地形文件完整性
        
        Args:
            filename: 文件名
            
        Returns:
            文件是否完整
        """
        try:
            if not os.path.exists(filename):
                print(f"✗ 文件不存在: {filename}")
                return False
                
            # 尝试加载文件
            terrain_data = self.load_terrain(filename)
            
            if terrain_data is None:
                print(f"✗ 地形文件无效: {filename}")
                return False
                
            # 检查必要数据是否存在
            required_keys = ['heightmap']
            missing_keys = [key for key in required_keys if key not in terrain_data or terrain_data[key] is None]
            
            if missing_keys:
                print(f"✗ 地形文件缺少必要数据: {missing_keys}")
                return False
                
            print(f"✓ 地形文件验证通过: {filename}")
            return True
            
        except Exception as e:
            print(f"✗ 地形文件验证失败: {e}")
            return False
            
    def compare_terrain_files(self, filename1: str, filename2: str) -> Dict[str, Any]:
        """
        比较两个地形文件
        
        Args:
            filename1: 第一个文件名
            filename2: 第二个文件名
            
        Returns:
            比较结果字典
        """
        try:
            # 加载两个文件
            terrain1 = self.load_terrain(filename1)
            terrain2 = self.load_terrain(filename2)
            
            if terrain1 is None or terrain2 is None:
                return {'error': '无法加载一个或两个地形文件'}
                
            comparison = {
                'file1': filename1,
                'file2': filename2,
                'identical': False,
                'differences': []
            }
            
            # 比较高度图
            if ('heightmap' in terrain1 and terrain1['heightmap'] is not None and
                'heightmap' in terrain2 and terrain2['heightmap'] is not None):
                heightmap1 = np.array(terrain1['heightmap'])
                heightmap2 = np.array(terrain2['heightmap'])
                
                if heightmap1.shape == heightmap2.shape:
                    # 计算差异
                    diff = np.abs(heightmap1 - heightmap2)
                    max_diff = np.max(diff)
                    mean_diff = np.mean(diff)
                    
                    comparison['heightmap_comparison'] = {
                        'shapes_match': True,
                        'max_difference': float(max_diff),
                        'mean_difference': float(mean_diff),
                        'identical': max_diff < 1e-6
                    }
                    
                    if max_diff >= 1e-6:
                        comparison['differences'].append('heightmap')
                else:
                    comparison['heightmap_comparison'] = {
                        'shapes_match': False
                    }
                    comparison['differences'].append('heightmap_shape')
            else:
                comparison['heightmap_comparison'] = {
                    'missing_data': True
                }
                
            # 比较其他数据
            maps_to_compare = ['biome_map', 'vegetation_map', 'water_map']
            for map_name in maps_to_compare:
                if (map_name in terrain1 and terrain1[map_name] is not None and
                    map_name in terrain2 and terrain2[map_name] is not None):
                    map1 = np.array(terrain1[map_name])
                    map2 = np.array(terrain2[map_name])
                    
                    if map1.shape == map2.shape:
                        if not np.array_equal(map1, map2):
                            comparison['differences'].append(map_name)
                    else:
                        comparison['differences'].append(f'{map_name}_shape')
                        
            # 检查是否完全相同
            comparison['identical'] = len(comparison['differences']) == 0
            
            return comparison
            
        except Exception as e:
            print(f"✗ 地形文件比较失败: {e}")
            return {'error': str(e)}
            
    def merge_terrain_files(self, filenames: List[str], output_filename: str) -> bool:
        """
        合并多个地形文件
        
        Args:
            filenames: 文件名列表
            output_filename: 输出文件名
            
        Returns:
            是否合并成功
        """
        try:
            if len(filenames) < 2:
                print("✗ 至少需要两个文件才能合并")
                return False
                
            print(f"✓ 开始合并 {len(filenames)} 个地形文件...")
            
            # 加载所有文件
            terrains = []
            for filename in filenames:
                terrain = self.load_terrain(filename)
                if terrain is None:
                    print(f"✗ 无法加载文件: {filename}")
                    return False
                terrains.append(terrain)
                
            # 创建合并后的地形数据
            merged_terrain = {}
            
            # 合并高度图（取平均值）
            heightmaps = [t.get('heightmap') for t in terrains if t.get('heightmap') is not None]
            if heightmaps:
                # 转换为numpy数组
                np_heightmaps = [np.array(h) for h in heightmaps]
                # 确保所有高度图尺寸相同
                if all(h.shape == np_heightmaps[0].shape for h in np_heightmaps):
                    # 计算平均值
                    merged_heightmap = np.mean(np_heightmaps, axis=0)
                    merged_terrain['heightmap'] = merged_heightmap
                else:
                    print("✗ 高度图尺寸不匹配，无法合并")
                    return False
                    
            # 合并其他数据（这里简化为取第一个文件的数据）
            if terrains:
                first_terrain = terrains[0]
                for key in ['biome_map', 'vegetation_map', 'water_map', 'stats']:
                    if key in first_terrain and first_terrain[key] is not None:
                        merged_terrain[key] = first_terrain[key]
                        
            # 保存合并后的地形
            success = self.save_terrain(output_filename, merged_terrain)
            
            if success:
                print(f"✓ 地形文件合并完成: {output_filename}")
                return True
            else:
                print("✗ 地形文件合并失败")
                return False
                
        except Exception as e:
            print(f"✗ 地形文件合并失败: {e}")
            import traceback
            traceback.print_exc()
            return False
            
    def convert_terrain_format(self, input_filename: str, output_filename: str, 
                              output_format: str) -> bool:
        """
        转换地形文件格式
        
        Args:
            input_filename: 输入文件名
            output_filename: 输出文件名
            output_format: 输出格式
            
        Returns:
            是否转换成功
        """
        try:
            # 验证输出格式
            if output_format not in self.supported_formats:
                print(f"✗ 不支持的输出格式: {output_format}")
                return False
                
            print(f"✓ 开始转换地形格式: {input_filename} -> {output_filename} ({output_format})")
            
            # 加载输入文件
            terrain_data = self.load_terrain(input_filename)
            
            if terrain_data is None:
                print("✗ 无法加载输入文件")
                return False
                
            # 保存为新格式
            original_format = self.serialization_params['default_format']
            self.serialization_params['default_format'] = output_format
            
            success = self.save_terrain(output_filename, terrain_data, format=output_format)
            
            # 恢复原始格式设置
            self.serialization_params['default_format'] = original_format
            
            if success:
                print("✓ 地形格式转换完成")
                return True
            else:
                print("✗ 地形格式转换失败")
                return False
                
        except Exception as e:
            print(f"✗ 地形格式转换失败: {e}")
            import traceback
            traceback.print_exc()
            return False