"""
地形影响系统
负责模拟地形特征对植被分布和生态系统的影响
"""

import time
from typing import Dict, Any, List, Optional, Tuple
import math
import random

class TerrainInfluence:
    """
    地形影响系统
    负责模拟地形特征（坡度、海拔、朝向等）对植被分布和生态系统的影响
    """
    
    def __init__(self, plugin):
        """
        初始化地形影响系统
        
        Args:
            plugin: 植被和生态系统插件实例
        """
        self.plugin = plugin
        self.enabled = False
        self.initialized = False
        
        # 地形因子定义
        self.terrain_factors = {
            'elevation': {
                'name': '海拔',
                'description': '海拔高度对植被的影响',
                'optimal_range': (0, 2000),    # 最佳海拔范围(米)
                'stress_threshold': 3000,      # 压力阈值(米)
                'impact_weight': 0.3           # 影响权重
            },
            'slope': {
                'name': '坡度',
                'description': '坡度对植被的影响',
                'optimal_range': (0, 30),      # 最佳坡度范围(度)
                'stress_threshold': 60,        # 压力阈值(度)
                'impact_weight': 0.2
            },
            'aspect': {
                'name': '朝向',
                'description': '坡面朝向对植被的影响',
                'optimal_range': (135, 225),   # 最佳朝向(东南-西南)
                'stress_direction': (0, 180),  # 不利朝向(北向)
                'impact_weight': 0.15
            },
            'soil_depth': {
                'name': '土壤深度',
                'description': '土壤深度对植被根系的影响',
                'optimal_range': (0.5, 2.0),   # 最佳土壤深度(米)
                'stress_threshold': 0.2,       # 压力阈值(米)
                'impact_weight': 0.25
            },
            'water_accumulation': {
                'name': '积水',
                'description': '地表积水对植被的影响',
                'optimal_range': (0, 0.3),     # 最佳积水深度(米)
                'stress_threshold': 0.5,       # 压力阈值(米)
                'impact_weight': 0.1
            }
        }
        
        # 地形影响模型
        self.influence_models = {
            'linear': {
                'name': '线性模型',
                'description': '线性影响关系'
            },
            'exponential': {
                'name': '指数模型',
                'description': '指数影响关系'
            },
            'threshold': {
                'name': '阈值模型',
                'description': '基于阈值的影响'
            },
            'combined': {
                'name': '组合模型',
                'description': '综合多种因子的影响'
            }
        }
        
        # 地形数据缓存
        self.terrain_cache = {}
        self.cache_config = {
            'max_size': 1000,              # 最大缓存大小
            'expiration_time': 300,        # 过期时间(秒)
            'update_interval': 60          # 更新间隔(秒)
        }
        
        # 地形微气候效应
        self.microclimate_effects = {
            'temperature_variation': 0.0,   # 温度变化
            'humidity_variation': 0.0,      # 湿度变化
            'wind_shelter': 0.0,           # 风力遮蔽
            'radiation_exposure': 0.0      # 辐射暴露
        }
        
        # 地形适应性参数
        self.adaptation_params = {
            'adaptation_rate': 0.01,        # 适应速率
            'genetic_diversity': 0.7,       # 遗传多样性
            'migration_capability': 0.3,    # 迁移能力
            'stress_tolerance': 0.5         # 压力耐受性
        }
        
        # 统计信息
        self.terrain_stats = {
            'influence_calculations': 0,
            'cache_hits': 0,
            'cache_misses': 0,
            'microclimate_updates': 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.terrain_cache.clear()
            self.initialized = False
            print("✓ 地形影响系统资源已清理")
            
        except Exception as e:
            print(f"✗ 地形影响系统资源清理失败: {e}")
            import traceback
            traceback.print_exc()
            
    def update(self, dt: float):
        """
        更新地形影响系统状态
        
        Args:
            dt: 时间增量
        """
        try:
            if not self.enabled:
                return
                
            # 更新地形缓存
            self._update_terrain_cache()
            
            # 更新微气候效应
            self._update_microclimate_effects()
            
        except Exception as e:
            print(f"✗ 地形影响系统更新失败: {e}")
            import traceback
            traceback.print_exc()
            
    def _update_terrain_cache(self):
        """更新地形数据缓存"""
        try:
            current_time = time.time()
            
            # 清理过期缓存
            expired_keys = []
            for key, (timestamp, _) in self.terrain_cache.items():
                if current_time - timestamp > self.cache_config['expiration_time']:
                    expired_keys.append(key)
                    
            for key in expired_keys:
                del self.terrain_cache[key]
                
        except Exception as e:
            print(f"✗ 地形缓存更新失败: {e}")
            
    def _update_microclimate_effects(self):
        """更新微气候效应"""
        try:
            # 在实际实现中，这里会根据地形特征更新微气候效应
            self.terrain_stats['microclimate_updates'] += 1
        except Exception as e:
            print(f"✗ 微气候效应更新失败: {e}")
            
    def calculate_terrain_influence(self, position: Tuple[float, float, float], 
                                  vegetation_type: str = None) -> Dict[str, float]:
        """
        计算地形对植被的影响
        
        Args:
            position: 位置坐标 (x, y, z)
            vegetation_type: 植被类型（可选）
            
        Returns:
            地形影响因子字典
        """
        try:
            # 检查缓存
            cache_key = f"{position}_{vegetation_type or 'general'}"
            current_time = time.time()
            
            if cache_key in self.terrain_cache:
                timestamp, cached_result = self.terrain_cache[cache_key]
                if current_time - timestamp < self.cache_config['expiration_time']:
                    self.terrain_stats['cache_hits'] += 1
                    return cached_result
                    
            self.terrain_stats['cache_misses'] += 1
            
            # 获取地形数据
            terrain_data = self._get_terrain_data(position)
            
            # 计算各因子影响
            influence_factors = {}
            total_weight = 0.0
            weighted_sum = 0.0
            
            for factor_name, factor_info in self.terrain_factors.items():
                if factor_name in terrain_data:
                    factor_value = terrain_data[factor_name]
                    factor_influence = self._calculate_factor_influence(
                        factor_name, factor_value, factor_info
                    )
                    
                    influence_factors[factor_name] = factor_influence
                    weight = factor_info['impact_weight']
                    weighted_sum += factor_influence * weight
                    total_weight += weight
                    
            # 计算综合影响
            if total_weight > 0:
                overall_influence = weighted_sum / total_weight
            else:
                overall_influence = 1.0
                
            influence_factors['overall'] = overall_influence
            
            # 缓存结果
            self.terrain_cache[cache_key] = (current_time, influence_factors)
            
            # 限制缓存大小
            if len(self.terrain_cache) > self.cache_config['max_size']:
                # 移除最旧的条目
                oldest_key = min(self.terrain_cache.keys(), 
                               key=lambda k: self.terrain_cache[k][0])
                del self.terrain_cache[oldest_key]
                
            self.terrain_stats['influence_calculations'] += 1
            
            return influence_factors
            
        except Exception as e:
            print(f"✗ 地形影响计算失败: {e}")
            return {'overall': 1.0}
            
    def _get_terrain_data(self, position: Tuple[float, float, float]) -> Dict[str, float]:
        """
        获取指定位置的地形数据
        
        Args:
            position: 位置坐标 (x, y, z)
            
        Returns:
            地形数据字典
        """
        try:
            x, y, z = position
            
            # 简化的地形数据生成
            # 在实际实现中，这里会从真实的地形数据源获取信息
            terrain_data = {
                'elevation': y,  # 假设y坐标为海拔
                'slope': random.uniform(0, 45),  # 随机坡度
                'aspect': random.uniform(0, 360),  # 随机朝向
                'soil_depth': random.uniform(0.1, 3.0),  # 随机土壤深度
                'water_accumulation': random.uniform(0, 0.8)  # 随机积水深度
            }
            
            return terrain_data
            
        except Exception as e:
            print(f"✗ 地形数据获取失败: {e}")
            return {}
            
    def _calculate_factor_influence(self, factor_name: str, factor_value: float, 
                                  factor_info: Dict[str, Any]) -> float:
        """
        计算单个地形因子的影响
        
        Args:
            factor_name: 因子名称
            factor_value: 因子值
            factor_info: 因子信息
            
        Returns:
            影响因子 (0.0-2.0)
        """
        try:
            optimal_range = factor_info['optimal_range']
            impact_weight = factor_info['impact_weight']
            
            min_optimal, max_optimal = optimal_range
            
            # 计算在最优范围内的适宜性
            if min_optimal <= factor_value <= max_optimal:
                suitability = 1.0
            else:
                # 计算距离最优范围的距离
                if factor_value < min_optimal:
                    distance = min_optimal - factor_value
                else:
                    distance = factor_value - max_optimal
                    
                # 指数衰减函数
                suitability = max(0.0, math.exp(-distance / (max_optimal - min_optimal)))
                
            # 应用压力阈值
            if 'stress_threshold' in factor_info:
                stress_threshold = factor_info['stress_threshold']
                if factor_name in ['elevation', 'slope', 'water_accumulation']:
                    if factor_value > stress_threshold:
                        # 超过压力阈值时进一步降低适宜性
                        excess = factor_value - stress_threshold
                        stress_factor = max(0.0, 1.0 - (excess / stress_threshold))
                        suitability *= stress_factor
                        
            return max(0.0, min(2.0, suitability))
            
        except Exception as e:
            print(f"✗ 因子影响计算失败: {e}")
            return 1.0
            
    def get_terrain_factors(self) -> Dict[str, Dict[str, Any]]:
        """
        获取地形因子定义
        
        Returns:
            地形因子字典
        """
        return self.terrain_factors.copy()
        
    def get_terrain_factor_info(self, factor_name: str) -> Optional[Dict[str, Any]]:
        """
        获取特定地形因子的信息
        
        Args:
            factor_name: 因子名称
            
        Returns:
            因子信息字典或None
        """
        return self.terrain_factors.get(factor_name)
        
    def set_terrain_factor_parameter(self, factor_name: str, parameter: str, value: Any):
        """
        设置地形因子参数
        
        Args:
            factor_name: 因子名称
            parameter: 参数名称
            value: 参数值
        """
        try:
            if factor_name in self.terrain_factors and parameter in self.terrain_factors[factor_name]:
                self.terrain_factors[factor_name][parameter] = value
                print(f"✓ 地形因子参数已设置: {factor_name}.{parameter} = {value}")
            else:
                print(f"✗ 无效的地形因子参数: {factor_name}.{parameter}")
                
        except Exception as e:
            print(f"✗ 地形因子参数设置失败: {e}")
            
    def get_influence_models(self) -> Dict[str, Dict[str, str]]:
        """
        获取影响模型
        
        Returns:
            影响模型字典
        """
        return self.influence_models.copy()
        
    def set_influence_model(self, model_name: str):
        """
        设置影响模型
        
        Args:
            model_name: 模型名称
        """
        try:
            if model_name in self.influence_models:
                # 在实际实现中，这里会设置当前使用的模型
                print(f"✓ 影响模型设置为: {self.influence_models[model_name]['name']}")
            else:
                print(f"✗ 无效的影响模型: {model_name}")
                
        except Exception as e:
            print(f"✗ 影响模型设置失败: {e}")
            
    def set_cache_config(self, config: Dict[str, Any]):
        """
        设置缓存配置
        
        Args:
            config: 缓存配置字典
        """
        try:
            self.cache_config.update(config)
            print(f"✓ 缓存配置已更新: {self.cache_config}")
        except Exception as e:
            print(f"✗ 缓存配置更新失败: {e}")
            
    def get_cache_config(self) -> Dict[str, Any]:
        """
        获取缓存配置
        
        Returns:
            缓存配置字典
        """
        return self.cache_config.copy()
        
    def clear_terrain_cache(self):
        """清空地形缓存"""
        try:
            self.terrain_cache.clear()
            print("✓ 地形缓存已清空")
        except Exception as e:
            print(f"✗ 地形缓存清空失败: {e}")
            
    def get_terrain_cache_info(self) -> Dict[str, Any]:
        """
        获取地形缓存信息
        
        Returns:
            缓存信息字典
        """
        try:
            return {
                'cache_size': len(self.terrain_cache),
                'max_size': self.cache_config['max_size'],
                'hit_rate': (self.terrain_stats['cache_hits'] / 
                           max(1, self.terrain_stats['cache_hits'] + self.terrain_stats['cache_misses']))
            }
        except Exception as e:
            print(f"✗ 缓存信息获取失败: {e}")
            return {}
            
    def update_microclimate_effect(self, effect_name: str, value: float):
        """
        更新微气候效应
        
        Args:
            effect_name: 效应名称
            value: 效应值
        """
        try:
            if effect_name in self.microclimate_effects:
                self.microclimate_effects[effect_name] = value
                print(f"✓ 微气候效应已更新: {effect_name} = {value}")
            else:
                print(f"✗ 无效的微气候效应: {effect_name}")
                
        except Exception as e:
            print(f"✗ 微气候效应更新失败: {e}")
            
    def get_microclimate_effects(self) -> Dict[str, float]:
        """
        获取微气候效应
        
        Returns:
            微气候效应字典
        """
        return self.microclimate_effects.copy()
        
    def set_adaptation_parameter(self, parameter: str, value: float):
        """
        设置适应性参数
        
        Args:
            parameter: 参数名称
            value: 参数值
        """
        try:
            if parameter in self.adaptation_params:
                self.adaptation_params[parameter] = max(0.0, min(1.0, value))
                print(f"✓ 适应性参数已设置: {parameter} = {value}")
            else:
                print(f"✗ 无效的适应性参数: {parameter}")
                
        except Exception as e:
            print(f"✗ 适应性参数设置失败: {e}")
            
    def get_adaptation_parameters(self) -> Dict[str, float]:
        """
        获取适应性参数
        
        Returns:
            适应性参数字典
        """
        return self.adaptation_params.copy()
        
    def simulate_terrain_adaptation(self, vegetation_type: str, 
                                  terrain_conditions: Dict[str, float]) -> float:
        """
        模拟植被对地形的适应过程
        
        Args:
            vegetation_type: 植被类型
            terrain_conditions: 地形条件
            
        Returns:
            适应性评分 (0.0-1.0)
        """
        try:
            # 获取植被的地形偏好
            if self.plugin.vegetation_manager:
                veg_info = self.plugin.vegetation_manager.get_vegetation_info(vegetation_type)
                if veg_info:
                    # 基于植被类型和地形条件计算适应性
                    adaptation_score = self._calculate_adaptation_score(vegetation_type, terrain_conditions)
                    return adaptation_score
                    
            # 默认适应性评分
            return 0.5
            
        except Exception as e:
            print(f"✗ 地形适应模拟失败: {e}")
            return 0.5
            
    def _calculate_adaptation_score(self, vegetation_type: str, 
                                  terrain_conditions: Dict[str, float]) -> float:
        """
        计算植被对地形的适应性评分
        
        Args:
            vegetation_type: 植被类型
            terrain_conditions: 地形条件
            
        Returns:
            适应性评分 (0.0-1.0)
        """
        try:
            # 简化的适应性计算
            scores = []
            
            for factor_name, factor_value in terrain_conditions.items():
                if factor_name in self.terrain_factors:
                    factor_info = self.terrain_factors[factor_name]
                    factor_influence = self._calculate_factor_influence(
                        factor_name, factor_value, factor_info
                    )
                    scores.append(factor_influence)
                    
            if scores:
                return sum(scores) / len(scores)
            return 0.5
            
        except Exception as e:
            print(f"✗ 适应性评分计算失败: {e}")
            return 0.5
            
    def get_terrain_stats(self) -> Dict[str, int]:
        """
        获取地形统计信息
        
        Returns:
            统计信息字典
        """
        return self.terrain_stats.copy()
        
    def reset_terrain_stats(self):
        """重置地形统计信息"""
        try:
            self.terrain_stats = {
                'influence_calculations': 0,
                'cache_hits': 0,
                'cache_misses': 0,
                'microclimate_updates': 0
            }
            print("✓ 地形统计信息已重置")
        except Exception as e:
            print(f"✗ 地形统计信息重置失败: {e}")
            
    def get_terrain_suitability_map(self, area: Tuple[Tuple[float, float], Tuple[float, float]], 
                                  resolution: float = 1.0) -> Dict[Tuple[float, float], float]:
        """
        获取区域内地形适宜性地图
        
        Args:
            area: 区域范围 ((min_x, min_z), (max_x, max_z))
            resolution: 分辨率
            
        Returns:
            适宜性地图字典 {(x, z): suitability}
        """
        try:
            (min_x, min_z), (max_x, max_z) = area
            suitability_map = {}
            
            x = min_x
            while x <= max_x:
                z = min_z
                while z <= max_z:
                    # 计算位置的适宜性
                    position = (x, 0, z)  # 假设y坐标为0
                    influence = self.calculate_terrain_influence(position)
                    suitability = influence.get('overall', 1.0)
                    
                    suitability_map[(x, z)] = suitability
                    
                    z += resolution
                x += resolution
                
            return suitability_map
            
        except Exception as e:
            print(f"✗ 适宜性地图生成失败: {e}")
            return {}