import numpy as np
import matplotlib.pyplot as plt
from matplotlib.colors import LinearSegmentedColormap
import matplotlib.animation as animation
from matplotlib.widgets import Button, RadioButtons
from mpl_toolkits.mplot3d import Axes3D

# 设置中文显示
plt.rcParams['font.sans-serif'] = ['SimHei', 'DejaVu Sans']
plt.rcParams['axes.unicode_minus'] = False

class ComplexGraphicsViewer:
    """复杂图形切换查看器"""
    
    def __init__(self):
        # 先初始化所有属性
        self.graphs = [
            '分形树 + 曼德勃罗特',
            '3D复杂曲面',
            '动态螺旋动画',
            '朱莉娅集',
            '分形火焰'
        ]
        self.current_graph = 0
        self.anim = None
        self.anim_running = True
        
        # 创建主窗口
        self.fig = plt.figure(figsize=(16, 9))
        self.fig.patch.set_facecolor('#0a0a2e')
        
        # 主绘图区
        self.ax_main = self.fig.add_axes([0.05, 0.05, 0.825, 0.845])
        self.ax_main.set_facecolor('#0a0a2e')
        
        # 控制面板
        self.create_control_panel()
        
        # 显示第一个图形
        self.switch_graph(0)
        
        # 绑定键盘事件
        self.fig.canvas.mpl_connect('key_press_event', self.on_key_press)
    
    def create_control_panel(self):
        """创建控制面板"""
        # 图形切换按钮
        ax_prev = self.fig.add_axes([0.902, 0.74, 0.086, 0.038])
        ax_next = self.fig.add_axes([0.903, 0.69, 0.084, 0.036])
        
        self.btn_prev = Button(ax_prev, '◀ 上一个', color='#333366', hovercolor='#444488')
        self.btn_next = Button(ax_next, '下一个 ▶', color='#333366', hovercolor='#444488')
        
        self.btn_prev.on_clicked(lambda x: self.switch_graph(-1))
        self.btn_next.on_clicked(lambda x: self.switch_graph(1))
        
        # 单选按钮选择图形 - 简化版本，不使用复杂样式
        ax_radio = self.fig.add_axes([0.898, 0.19, 0.092, 0.41])
        
        # 修复：使用正确的参数格式
        self.radio = RadioButtons(
            ax_radio, 
            self.graphs,
            activecolor='#6666ff'
        )
        
        # 单独设置样式
        for circle in self.radio.circles:
            circle.set_facecolor('#333366')
            circle.set_edgecolor('#6666ff')
            circle.set_linewidth(1.5)
        
        for label in self.radio.labels:
            label.set_color('white')
            label.set_fontsize(8.5)
        
        self.radio.on_clicked(self.on_radio_clicked)
        
        # 当前图形名称显示
        self.title_text = self.fig.text(
            0.462, 0.945, '', 
            ha='center', va='top', 
            fontsize=14, color='white', 
            fontweight='bold'
        )
        
        # 操作提示
        self.fig.text(
            0.912, 0.645, '快捷键:\n← → 切换\n空格 暂停/继续\nR 重置', 
            fontsize=7.5, color='#8888ff', 
            ha='left', va='top'
        )
    
    def switch_graph(self, direction):
        """切换图形"""
        if isinstance(direction, int):
            self.current_graph = (self.current_graph + direction) % len(self.graphs)
        else:
            self.current_graph = self.graphs.index(direction)
        
        # 停止当前动画
        if self.anim:
            self.anim.event_source.stop()
            self.anim = None
        
        # 获取要保留的控件
        keep_axes = [
            self.btn_prev.ax, 
            self.btn_next.ax, 
            self.radio.ax,
            self.title_text
        ]
        
        # 清除当前图形 - 移除所有非控件子图
        axes_to_remove = []
        for ax in self.fig.axes:
            if ax not in keep_axes:
                axes_to_remove.append(ax)
        
        for ax in axes_to_remove:
            try:
                ax.remove()
            except:
                pass
        
        # 重新创建主绘图区
        self.ax_main = self.fig.add_axes([0.048, 0.058, 0.828, 0.838])
        self.ax_main.set_facecolor('#0a0a2e')
        
        # 根据选择绘制不同图形
        graph_name = self.graphs[self.current_graph]
        self.title_text.set_text(f'当前图形: {graph_name}')
        
        if graph_name == '分形树 + 曼德勃罗特':
            self.draw_fractal_tree_and_mandelbrot()
        elif graph_name == '3D复杂曲面':
            self.draw_3d_surface()
        elif graph_name == '动态螺旋动画':
            self.draw_animated_spiral()
        elif graph_name == '朱莉娅集':
            self.draw_julia_set()
        elif graph_name == '分形火焰':
            self.draw_fractal_flame()
        
        self.fig.canvas.draw_idle()
    
    def on_radio_clicked(self, label):
        """单选按钮回调"""
        self.switch_graph(label)
    
    def on_key_press(self, event):
        """键盘事件处理"""
        if event.key == 'right':
            self.switch_graph(1)
        elif event.key == 'left':
            self.switch_graph(-1)
        elif event.key == ' ':
            if self.anim:
                if self.anim_running:
                    self.anim.event_source.stop()
                    self.anim_running = False
                else:
                    self.anim.event_source.start()
                    self.anim_running = True
        elif event.key == 'r':
            self.switch_graph(0)
    
    def draw_fractal_tree_and_mandelbrot(self):
        """绘制分形树和曼德勃罗特集"""
        # 移除主绘图区，创建两个子图
        self.ax_main.remove()
        
        ax1 = self.fig.add_axes([0.042, 0.068, 0.395, 0.832])
        ax2 = self.fig.add_axes([0.472, 0.062, 0.385, 0.848])
        
        ax1.set_facecolor('#0a0a2e')
        ax2.set_facecolor('#0a0a2e')
        
        # === 分形树 ===
        def draw_branch(x, y, length, angle, depth, max_depth=10):
            if depth > max_depth or length < 1:
                return
            
            end_x = x + length * np.cos(angle)
            end_y = y + length * np.sin(angle)
            
            color_intensity = 1 - depth / max_depth
            r, g, b = 0.4 + 0.3 * color_intensity, 0.25 + 0.5 * color_intensity, 0.05
            width = max(0.5, 4 * (1 - depth / max_depth))
            
            ax1.plot([x, end_x], [y, end_y], 
                    color=(r, g, b), linewidth=width, alpha=0.8)
            
            np.random.seed(int(depth * 100 + x * 10))
            variation = np.random.uniform(-0.3, 0.3)
            
            new_length = length * 0.68
            draw_branch(end_x, end_y, new_length, angle + 0.52 + variation, depth + 1, max_depth)
            draw_branch(end_x, end_y, new_length, angle - 0.52 - variation, depth + 1, max_depth)
            
            if depth < 5 and np.random.random() > 0.6:
                draw_branch(end_x, end_y, new_length * 0.76, angle + variation * 2, depth + 1, max_depth)
        
        ax1.set_xlim(-60, 135)
        ax1.set_ylim(-30, 175)
        ax1.set_aspect('equal')
        ax1.axis('off')
        ax1.set_title('🌳 分形生命树', fontsize=12, color='white', pad=10)
        
        draw_branch(38, 0, 29, np.pi/2, 0, 10)
        
        # === 曼德勃罗特集 ===
        resolution = 480
        xmin, xmax, ymin, ymax = -2.5, 1.5, -2, 2
        x = np.linspace(xmin, xmax, resolution)
        y = np.linspace(ymin, ymax, resolution)
        X, Y = np.meshgrid(x, y)
        C = X + 1j * Y
        
        max_iter = 155
        Z = np.zeros_like(C, dtype=np.complex128)
        M = np.full(C.shape, max_iter, dtype=int)
        
        for i in range(max_iter):
            mask = np.abs(Z) <= 2
            Z[mask] = Z[mask]**2 + C[mask]
            M[mask & (np.abs(Z) > 2)] = i
        
        colors = ['#000033', '#000066', '#000099', '#0033cc', '#0066ff',
                  '#0099ff', '#00ccff', '#00ffff', '#66ffcc', '#99ff99',
                  '#ccff66', '#ffff00', '#ffcc00', '#ff9900', '#ff6600',
                  '#ff3300', '#cc0000', '#990000', '#660000']
        cmap = LinearSegmentedColormap.from_list('custom', colors, N=256)
        
        ax2.imshow(M, cmap=cmap, extent=[xmin, xmax, ymin, ymax], aspect='equal')
        ax2.axis('off')
        ax2.set_title('🌀 曼德勃罗特集', fontsize=12, color='white', pad=10)
    
    def draw_3d_surface(self):
        """绘制3D复杂曲面"""
        ax = self.fig.add_axes([0.052, 0.056, 0.826, 0.812], projection='3d')
        ax.set_facecolor('#0a0a2e')
        
        x = np.linspace(-5, 5, 340)
        y = np.linspace(-5, 5, 342)
        X, Y = np.meshgrid(x, y)
        
        R = np.sqrt(X**2 + Y**2)
        Z = (np.sin(R) * np.cos(2*X) * np.sin(3*Y) / (R + 0.1) +
             0.5 * np.exp(-R/3) * np.cos(4*X + 3*Y) +
             0.3 * np.sin(np.sqrt(X**2 + Y**2) * 2))
        
        norm = plt.Normalize(Z.min(), Z.max())
        colors = plt.cm.viridis(norm(Z))
        
        ax.plot_surface(X, Y, Z, facecolors=colors, 
                       rstride=1, cstride=1,
                       alpha=0.92, antialiased=True)
        
        ax.view_init(elev=22, azim=48)
        ax.set_xlabel('X', color='white', fontsize=9)
        ax.set_ylabel('Y', color='white', fontsize=9)
        ax.set_zlabel('Z', color='white', fontsize=9)
        ax.tick_params(colors='white', labelsize=7)
        ax.set_title('🌊 3D复杂波形曲面', fontsize=12, color='white', pad=10)
    
    def draw_animated_spiral(self):
        """绘制动态螺旋动画"""
        ax = self.ax_main
        ax.set_xlim(-2.5, 2.5)
        ax.set_ylim(-2.5, 2.5)
        ax.set_aspect('equal')
        ax.axis('off')
        
        t = np.linspace(0, 28*np.pi, 1720)
        
        def animate(frame):
            ax.clear()
            ax.set_facecolor('#0a0a2e')
            ax.set_xlim(-2.5, 2.5)
            ax.set_ylim(-2.5, 2.5)
            ax.set_aspect('equal')
            ax.axis('off')
            
            current_t = t[:frame+1]
            r = 0.082 + 0.023 * current_t
            x = r * np.cos(current_t + frame * 0.004)
            y = r * np.sin(current_t + frame * 0.004)
            
            colors = plt.cm.hsv(np.linspace(0, 1, len(current_t)))
            
            for i in range(len(current_t)-1):
                ax.plot(x[i:i+2], y[i:i+2], 
                       color=colors[i], linewidth=2.5, alpha=0.85)
            
            circle = plt.Circle((0, 0), 0.145, color='gold', alpha=0.325)
            ax.add_patch(circle)
            
            ax.set_title(f'🌀 动态螺旋 - 帧 {frame}', 
                        fontsize=12, color='white')
            
            return ax,
        
        self.anim = animation.FuncAnimation(
            self.fig, animate, frames=720, 
            interval=14, blit=False
        )
    
    def draw_julia_set(self):
        """绘制朱莉娅集"""
        ax = self.ax_main
        ax.set_facecolor('#0a0a2e')
        
        # 朱莉娅集参数
        c = complex(-0.745, 0.205)
        
        resolution = 620
        xmin, xmax = -1.5, 1.5
        ymin, ymax = -1.5, 1.5
        
        x = np.linspace(xmin, xmax, resolution)
        y = np.linspace(ymin, ymax, resolution)
        X, Y = np.meshgrid(x, y)
        Z = X + 1j * Y
        
        max_iter = 225
        M = np.full(Z.shape, max_iter, dtype=int)
        
        for i in range(max_iter):
            mask = np.abs(Z) <= 2
            Z[mask] = Z[mask]**2 + c
            M[mask & (np.abs(Z) > 2)] = i
        
        # 自定义色彩映射
        colors_julia = ['#000000', '#080012', '#100025', '#180037',
                       '#20004a', '#28005c', '#381a73', '#483389',
                       '#584da0', '#6866b6', '#7880cd', '#8899e3',
                       '#99b3fa', '#b3ccff', '#cce6ff', '#ffffff']
        cmap = LinearSegmentedColormap.from_list('julia', colors_julia, N=420)
        
        im = ax.imshow(M, cmap=cmap, extent=[xmin, xmax, ymin, ymax], 
                      aspect='equal', interpolation='bilinear')
        ax.axis('off')
        ax.set_title(f'🔮 朱莉娅集 (c = {c.real:.3f} + {c.imag:.3f}i)', 
                    fontsize=12, color='white', pad=10)
    
    def draw_fractal_flame(self):
        """绘制分形火焰效果"""
        ax = self.ax_main
        ax.set_facecolor('#0a0a2e')
        
        # 使用混沌游戏生成分形火焰
        n_points = 78000
        
        # 定义变换函数
        def transform1(x, y):
            return 0.486 * x, 0.476 * y
        
        def transform2(x, y):
            return 0.496 * x + 0.508, 0.506 * y + 0.514
        
        def transform3(x, y):
            return 0.479 * x + 0.266, 0.481 * y + 0.263
        
        def transform4(x, y):
            return 0.502 * x + 0.757, 0.497 * y + 0.252
        
        transforms = [transform1, transform2, transform3, transform4]
        probabilities = [0.235, 0.275, 0.248, 0.242]
        
        # 生成点
        x, y = 0.528, 0.516
        points_x = []
        points_y = []
        
        for _ in range(n_points):
            idx = np.random.choice(len(transforms), p=probabilities)
            x, y = transforms[idx](x, y)
            points_x.append(x)
            points_y.append(y)
        
        # 创建密度图
        heatmap, xedges, yedges = np.histogram2d(
            points_x, points_y, bins=430,
            range=[[0, 1], [0, 1]]
        )
        
        # 应用对数变换增强视觉效果
        heatmap = np.log(heatmap + 1)
        
        # 自定义火焰色彩映射
        colors_flame = ['#000000', '#140000', '#280000', '#3d0000',
                       '#520000', '#661400', '#7a2800', '#8f3d00',
                       '#a35200', '#b86600', '#cc7a00', '#e08f00',
                       '#f5a300', '#ffba40', '#ffd180', '#ffe8bf', '#ffffff']
        cmap = LinearSegmentedColormap.from_list('flame', colors_flame, N=360)
        
        ax.imshow(heatmap.T, cmap=cmap, extent=[0, 1, 0, 1], 
                 aspect='equal', origin='lower', interpolation='gaussian')
        ax.axis('off')
        ax.set_title('🔥 分形火焰', fontsize=12, color='white', pad=10)

# 启动查看器
if __name__ == "__main__":
    print("🎨 复杂图形切换查看器")
    print("=" * 40)
    print("📋 可用图形:")
    print("  1. 分形树 + 曼德勃罗特")
    print("  2. 3D复杂曲面")
    print("  3. 动态螺旋动画")
    print("  4. 朱莉娅集")
    print("  5. 分形火焰")
    print("=" * 40)
    print("⌨️ 快捷键:")
    print("  ← → : 切换图形")
    print("  空格 : 暂停/继续动画")
    print("  R    : 重置")
    print("=" * 40)
    
    viewer = ComplexGraphicsViewer()
    plt.show()