"""
地形图层系统
提供完整的地形图层管理功能，支持多层纹理混合、Alpha混合等高级功能
"""

from panda3d.core import Texture, TextureStage, PNMImage, Filename
import os

class TerrainLayerSystem:
    """
    地形图层系统类
    提供完整的地形图层管理功能
    """
    
    def __init__(self, world):
        self.world = world
        self.terrain_layers = {}  # 存储地形图层信息
        
    def create_layered_terrain(self, terrain_node, layer_configs):
        """
        创建分层地形
        layer_configs: 图层配置列表，每个配置包含纹理路径、混合贴图等信息
        """
        try:
            # 清除现有的地形纹理
            terrain_node.clearTexture()
            
            # 为每个图层创建纹理阶段
            for i, layer_config in enumerate(layer_configs):
                # 加载漫反射纹理
                if 'diffuse' in layer_config:
                    diffuse_texture = self._load_texture(layer_config['diffuse'])
                    if diffuse_texture:
                        diffuse_stage = TextureStage(f"diffuse_{i}")
                        diffuse_stage.setSort(i * 10)  # 设置排序
                        terrain_node.setTexture(diffuse_stage, diffuse_texture)
                        
                # 加载法线纹理
                if 'normal' in layer_config:
                    normal_texture = self._load_texture(layer_config['normal'])
                    if normal_texture:
                        normal_stage = TextureStage(f"normal_{i}")
                        normal_stage.setMode(TextureStage.M_normal)  # 设置为法线贴图模式
                        normal_stage.setSort(i * 10 + 1)
                        terrain_node.setTexture(normal_stage, normal_texture)
                        
                # 加载高光纹理
                if 'specular' in layer_config:
                    specular_texture = self._load_texture(layer_config['specular'])
                    if specular_texture:
                        specular_stage = TextureStage(f"specular_{i}")
                        specular_stage.setMode(TextureStage.M_specular)  # 设置为高光贴图模式
                        specular_stage.setSort(i * 10 + 2)
                        terrain_node.setTexture(specular_stage, specular_texture)
                        
                # 加载混合纹理（控制图层混合）
                if 'blend' in layer_config:
                    blend_texture = self._load_texture(layer_config['blend'])
                    if blend_texture:
                        blend_stage = TextureStage(f"blend_{i}")
                        blend_stage.setMode(TextureStage.M_blend)  # 设置为混合模式
                        blend_stage.setSort(i * 10 + 3)
                        terrain_node.setTexture(blend_stage, blend_texture)
                        
                # 加载Alpha纹理（控制透明度）
                if 'alpha' in layer_config:
                    alpha_texture = self._load_texture(layer_config['alpha'])
                    if alpha_texture:
                        alpha_stage = TextureStage(f"alpha_{i}")
                        alpha_stage.setMode(TextureStage.M_modulate)  # 设置为调制模式
                        alpha_stage.setSort(i * 10 + 4)
                        terrain_node.setTexture(alpha_stage, alpha_texture)
                        
            # 保存图层信息
            self.terrain_layers[terrain_node] = layer_configs
            
            print(f"为地形创建 {len(layer_configs)} 个图层系统")
            return True
            
        except Exception as e:
            print(f"创建分层地形时出错: {e}")
            return False
            
    def add_layer(self, terrain_node, layer_config, layer_index=None):
        """
        为地形添加新图层
        """
        try:
            if terrain_node not in self.terrain_layers:
                # 如果地形还没有图层系统，创建一个新的
                self.terrain_layers[terrain_node] = []
                
            layers = self.terrain_layers[terrain_node]
            
            # 确定插入位置
            if layer_index is None:
                layer_index = len(layers)
                
            # 插入新图层
            layers.insert(layer_index, layer_config)
            
            # 重新应用所有图层
            return self.create_layered_terrain(terrain_node, layers)
            
        except Exception as e:
            print(f"添加图层时出错: {e}")
            return False
            
    def remove_layer(self, terrain_node, layer_index):
        """
        移除地形的指定图层
        """
        try:
            if terrain_node not in self.terrain_layers:
                print("地形没有图层系统")
                return False
                
            layers = self.terrain_layers[terrain_node]
            
            if layer_index < 0 or layer_index >= len(layers):
                print("图层索引超出范围")
                return False
                
            # 移除图层
            layers.pop(layer_index)
            
            # 重新应用所有图层
            return self.create_layered_terrain(terrain_node, layers)
            
        except Exception as e:
            print(f"移除图层时出错: {e}")
            return False
            
    def update_layer(self, terrain_node, layer_index, layer_config):
        """
        更新地形图层
        """
        try:
            if terrain_node not in self.terrain_layers:
                print("地形没有图层系统")
                return False
                
            layers = self.terrain_layers[terrain_node]
            
            if layer_index < 0 or layer_index >= len(layers):
                print("图层索引超出范围")
                return False
                
            # 更新图层配置
            layers[layer_index] = layer_config
            
            # 重新应用所有图层
            return self.create_layered_terrain(terrain_node, layers)
            
        except Exception as e:
            print(f"更新图层时出错: {e}")
            return False
            
    def get_layer_info(self, terrain_node, layer_index):
        """
        获取图层信息
        """
        try:
            if terrain_node not in self.terrain_layers:
                print("地形没有图层系统")
                return None
                
            layers = self.terrain_layers[terrain_node]
            
            if layer_index < 0 or layer_index >= len(layers):
                print("图层索引超出范围")
                return None
                
            return layers[layer_index]
            
        except Exception as e:
            print(f"获取图层信息时出错: {e}")
            return None
            
    def blend_layers(self, terrain_node, blend_map_path):
        """
        使用混合图混合所有图层
        """
        try:
            if terrain_node not in self.terrain_layers:
                print("地形没有图层系统")
                return False
                
            # 加载混合图
            blend_texture = self._load_texture(blend_map_path)
            if not blend_texture:
                print("无法加载混合图")
                return False
                
            # 应用混合图到所有图层
            blend_stage = TextureStage("global_blend")
            blend_stage.setMode(TextureStage.M_blend)
            blend_stage.setSort(1000)  # 确保在最后应用
            terrain_node.setTexture(blend_stage, blend_texture)
            
            print(f"应用全局混合图: {blend_map_path}")
            return True
            
        except Exception as e:
            print(f"混合图层时出错: {e}")
            return False
            
    def generate_blend_map(self, terrain_info, layer_weights, output_path):
        """
        生成图层混合图
        layer_weights: 每个图层的权重列表
        """
        try:
            heightfield = terrain_info['heightfield']
            if not heightfield:
                print("无法获取地形高度图数据")
                return False
                
            width = heightfield.getXSize()
            height = heightfield.getYSize()
            
            # 创建混合图
            blend_image = PNMImage(width, height, 4)  # RGBA格式
            
            # 根据高度和权重生成混合图
            for y in range(height):
                for x in range(width):
                    height_value = heightfield.getRed(x, y)
                    
                    # 根据高度值分配权重
                    weights = self._calculate_layer_weights(height_value, layer_weights)
                    
                    # 设置RGBA值
                    blend_image.setRed(x, y, weights[0] if len(weights) > 0 else 0)
                    blend_image.setGreen(x, y, weights[1] if len(weights) > 1 else 0)
                    blend_image.setBlue(x, y, weights[2] if len(weights) > 2 else 0)
                    blend_image.setAlpha(x, y, weights[3] if len(weights) > 3 else 0)
                    
            # 保存混合图
            output_dir = os.path.dirname(output_path)
            if not os.path.exists(output_dir):
                os.makedirs(output_dir)
                
            success = blend_image.write(Filename.fromOsSpecific(output_path))
            if success:
                print(f"混合图生成成功: {output_path}")
                return True
            else:
                print(f"混合图生成失败: {output_path}")
                return False
                
        except Exception as e:
            print(f"生成混合图时出错: {e}")
            return False
            
    def _calculate_layer_weights(self, height_value, layer_weights):
        """
        根据高度值计算图层权重
        """
        # 简单的高度分区方法
        weights = [0.0] * len(layer_weights)
        
        if height_value < 0.3:  # 低地
            weights[0] = 1.0
        elif height_value < 0.6:  # 中等地
            weights[1] = 1.0
        elif height_value < 0.8:  # 高地
            weights[2] = 1.0
        else:  # 山峰
            weights[3] = 1.0 if len(weights) > 3 else 0
            
        return weights
        
    def _load_texture(self, texture_path):
        """
        加载纹理
        """
        try:
            if not os.path.exists(texture_path):
                print(f"纹理文件不存在: {texture_path}")
                return None
                
            texture = self.world.loader.loadTexture(texture_path)
            if texture:
                print(f"纹理加载成功: {texture_path}")
                return texture
            else:
                print(f"纹理加载失败: {texture_path}")
                return None
        except Exception as e:
            print(f"加载纹理时出错: {e}")
            return None
            
    def create_texture_array(self, texture_paths, array_name):
        """
        创建纹理数组
        """
        try:
            # 加载所有纹理
            textures = []
            for path in texture_paths:
                texture = self._load_texture(path)
                if texture:
                    textures.append(texture)
                    
            if not textures:
                print("没有成功加载任何纹理")
                return None
                
            # 创建纹理数组
            # 注意：Panda3D的纹理数组创建比较复杂，这里只是一个概念实现
            print(f"创建纹理数组: {array_name}，包含 {len(textures)} 个纹理")
            return textures  # 临时返回纹理列表
            
        except Exception as e:
            print(f"创建纹理数组时出错: {e}")
            return None
            
    def apply_texture_array(self, terrain_node, texture_array, array_name):
        """
        应用纹理数组到地形
        """
        try:
            if not texture_array:
                print("纹理数组为空")
                return False
                
            # 为每个纹理创建纹理阶段
            for i, texture in enumerate(texture_array):
                texture_stage = TextureStage(f"{array_name}_{i}")
                texture_stage.setSort(i)
                terrain_node.setTexture(texture_stage, texture)
                
            print(f"应用纹理数组: {array_name}")
            return True
            
        except Exception as e:
            print(f"应用纹理数组时出错: {e}")
            return False
            
    def save_layer_config(self, terrain_node, config_path):
        """
        保存图层配置到文件
        """
        try:
            if terrain_node not in self.terrain_layers:
                print("地形没有图层系统")
                return False
                
            import json
            
            # 保存图层配置
            layers = self.terrain_layers[terrain_node]
            
            # 确保输出目录存在
            output_dir = os.path.dirname(config_path)
            if not os.path.exists(output_dir):
                os.makedirs(output_dir)
                
            with open(config_path, 'w', encoding='utf-8') as f:
                json.dump(layers, f, indent=2, ensure_ascii=False)
                
            print(f"图层配置保存成功: {config_path}")
            return True
            
        except Exception as e:
            print(f"保存图层配置时出错: {e}")
            return False
            
    def load_layer_config(self, terrain_node, config_path):
        """
        从文件加载图层配置
        """
        try:
            if not os.path.exists(config_path):
                print(f"图层配置文件不存在: {config_path}")
                return False
                
            import json
            
            # 加载图层配置
            with open(config_path, 'r', encoding='utf-8') as f:
                layers = json.load(f)
                
            # 应用图层配置
            self.terrain_layers[terrain_node] = layers
            return self.create_layered_terrain(terrain_node, layers)
            
        except Exception as e:
            print(f"加载图层配置时出错: {e}")
            return False