"""Scene manager conversion and tileset operations."""

import os
import shutil
import time
import json
import aiohttp
import asyncio
import inspect
from pathlib import Path

from panda3d.core import (
    ModelPool, ModelRoot, Filename, NodePath, GeomNode, Material, Vec4, Vec3,
    MaterialAttrib, ColorAttrib, Point3, CollisionNode, CollisionSphere, CollisionBox,
    BitMask32, TransparencyAttrib, LColor, TransformState, RenderModeAttrib
)
from panda3d.egg import EggData, EggVertexPool
from direct.actor.Actor import Actor
from RenderPipelineFile.rpplugins.smaa.jitters import halton_seq
from scene import util

class SceneManagerConvertTilesMixin:
    def _get_tree_widget(self):
        """安全获取树形控件"""
        try:
            if (hasattr(self.world, 'interface_manager') and
                    hasattr(self.world.interface_manager, 'treeWidget')):
                return self.world.interface_manager.treeWidget
        except AttributeError:
            pass
        return None

    def _shouldConvertToGLB(self, filepath):
        """判断是否应该转换为GLB格式"""
        ext = os.path.splitext(filepath)[1].lower()
        # 需要转换的格式：FBX, OBJ, DAE等（但不转换已经是GLB/GLTF的）
        convert_formats = ['.fbx', '.obj', '.dae', '.3ds', '.blend']
        return ext in convert_formats

    def _convertToGLBWithProgress(self, filepath):
        """带进度显示的GLB转换"""
        try:
            from PyQt5.QtWidgets import QProgressDialog, QApplication
            from PyQt5.QtCore import Qt
            
            # 创建进度对话框
            progress = QProgressDialog("正在转换模型格式以获得更好的动画支持...", "取消", 0, 100)
            progress.setWindowTitle("模型格式转换")
            progress.setWindowModality(Qt.WindowModal)
            progress.show()
            QApplication.processEvents()
            
            try:
                result = self._convertToGLB(filepath, progress)
                progress.hide()
                return result
            except Exception as e:
                progress.hide()
                print(f"转换过程出错: {e}")
                return None
                
        except ImportError:
            # 如果没有 PyQt5，直接转换
            return self._convertToGLB(filepath)

    def _convertToGLB(self, filepath, progress=None):
        """将模型文件转换为GLB格式"""
        try:
            print(f"[GLB转换] 开始转换: {filepath}")
            
            if progress:
                progress.setValue(10)
                progress.setLabelText("准备转换...")
                from PyQt5.QtWidgets import QApplication
                QApplication.processEvents()
            
            # 准备输出路径
            base_name = os.path.splitext(os.path.basename(filepath))[0]
            output_dir = os.path.dirname(filepath)
            glb_path = os.path.join(output_dir, f"{base_name}_auto_converted.glb")
            
            # 如果已经存在转换后的文件，直接使用
            if os.path.exists(glb_path):
                # 检查文件时间，如果原文件更新则重新转换
                original_time = os.path.getmtime(filepath)
                converted_time = os.path.getmtime(glb_path)
                if converted_time > original_time:
                    print(f"[GLB转换] 使用现有转换文件: {glb_path}")
                    if progress:
                        progress.setValue(100)
                    return glb_path
            
            if progress:
                progress.setValue(20)
                progress.setLabelText("尝试 Blender 转换...")
                QApplication.processEvents()
            
            # 方法1: 使用 Blender 进行转换
            if self._convertWithBlender(filepath, glb_path, progress):
                return glb_path
            
            if progress:
                progress.setValue(60)
                progress.setLabelText("尝试 FBX2glTF 转换...")
                QApplication.processEvents()
            
            # 方法2: 使用 FBX2glTF (如果可用)
            if self._convertWithFBX2glTF(filepath, glb_path, progress):
                return glb_path
            
            if progress:
                progress.setValue(80)
                progress.setLabelText("尝试 Assimp 转换...")
                QApplication.processEvents()
            
            # 方法3: 使用 Assimp
            if self._convertWithAssimp(filepath, glb_path, progress):
                return glb_path
            
            #print(f"[GLB转换] 所有转换方法都失败，既然没有可以转换格式的工具和环境那么就用原始文件，不一定非要转换")
            return None
            
        except Exception as e:
            print(f"[GLB转换] 转换过程出错: {e}")
            return None

    def _convertWithBlender(self, input_path, output_path, progress=None):
        """使用 Blender 进行转换"""
        try:
            import subprocess
            import tempfile
            
            print(f"[Blender转换] {input_path} → {output_path}")
            
            # 创建 Blender 脚本
            script_content = f'''
import bpy
import sys
import os

# 清理默认场景
bpy.ops.object.select_all(action='SELECT')
bpy.ops.object.delete(use_global=False)

print("开始导入文件...")

# 根据文件类型选择导入方法
input_file = "{input_path}"
output_file = "{output_path}"

try:
    ext = os.path.splitext(input_file)[1].lower()
    
    if ext == '.fbx':
        bpy.ops.import_scene.fbx(filepath=input_file)
    elif ext == '.obj':
        bpy.ops.import_scene.obj(filepath=input_file)
    elif ext == '.dae':
        bpy.ops.wm.collada_import(filepath=input_file)
    elif ext == '.blend':
        bpy.ops.wm.open_mainfile(filepath=input_file)
    else:
        print(f"不支持的格式: {{ext}}")
        sys.exit(1)
    
    print("导入成功，开始导出GLB...")
    
    # 导出为 GLB，保留动画
    bpy.ops.export_scene.gltf(
        filepath=output_file,
        export_format='GLB',
        export_animations=True,
        export_force_sampling=True,
        export_frame_range=True,
        export_current_frame=False,
        export_skins=True,
        export_morph=True,
        export_lights=True,
        export_cameras=False
    )
    
    print("GLB导出成功！")
    
except Exception as e:
    print(f"转换失败: {{e}}")
    sys.exit(1)
'''
            
            # 写入临时脚本文件
            with tempfile.NamedTemporaryFile(mode='w', suffix='.py', delete=False) as temp_file:
                temp_file.write(script_content)
                script_path = temp_file.name
            
            try:
                # 执行 Blender 转换
                result = subprocess.run([
                    'blender', '--background', '--python', script_path
                ], capture_output=True, text=True, timeout=180)
                
                # 清理临时文件
                os.unlink(script_path)
                
                if result.returncode == 0 and os.path.exists(output_path):
                    print(f"[Blender转换] 转换成功")
                    return True
                else:
                    print(f"[Blender转换] 转换失败: {result.stderr}")
                    return False
                    
            except subprocess.TimeoutExpired:
                print(f"[Blender转换] 转换超时")
                return False
            except FileNotFoundError:
                print(f"[Blender转换] Blender 未安装")
                return False
                
        except Exception as e:
            print(f"[Blender转换] 转换过程出错: {e}")
            return False

    def _convertWithFBX2glTF(self, input_path, output_path, progress=None):
        """使用 FBX2glTF 进行转换（仅支持FBX）"""
        try:
            import subprocess
            
            if not input_path.lower().endswith('.fbx'):
                return False
                
            print(f"[FBX2glTF转换] {input_path} → {output_path}")
            
            # 使用 FBX2glTF 转换
            result = subprocess.run([
                'FBX2glTF', input_path, '--output', output_path, '--binary'
            ], capture_output=True, text=True, timeout=120)
            
            if result.returncode == 0 and os.path.exists(output_path):
                print(f"[FBX2glTF转换] 转换成功")
                return True
            else:
                print(f"[FBX2glTF转换] 转换失败: {result.stderr}")
                return False
                
        except subprocess.TimeoutExpired:
            print(f"[FBX2glTF转换] 转换超时")
            return False
        except FileNotFoundError:
            print(f"[FBX2glTF转换] FBX2glTF 未安装")
            return False
        except Exception as e:
            print(f"[FBX2glTF转换] 转换过程出错: {e}")
            return False

    def _convertWithAssimp(self, input_path, output_path, progress=None):
        """使用 PyAssimp 进行转换"""
        try:
            import pyassimp
            
            print(f"[PyAssimp转换] {input_path} → {output_path}")
            
            # 加载模型
            scene = pyassimp.load(input_path)
            if not scene:
                print(f"[PyAssimp转换] 加载模型失败")
                return False
            
            if progress:
                progress.setValue(30)
            
            # 导出为GLB格式
            pyassimp.export(scene, output_path, "glb2")
            
            if progress:
                progress.setValue(80)
            
            # 释放资源
            pyassimp.release(scene)
            
            if os.path.exists(output_path):
                print(f"[PyAssimp转换] 转换成功")
                return True
            else:
                print(f"[PyAssimp转换] 转换失败: 输出文件未生成")
                return False
                
        except ImportError:
            print(f"[PyAssimp转换] PyAssimp 未安装")
            return False
        except Exception as e:
            print(f"[PyAssimp转换] 转换过程出错: {e}")
            return False

    def _check_async_task(self, panda3d_task):
        # 检查 asyncio 任务是否完成
        if hasattr(self, '_current_asyncio_task'):
            if self._current_asyncio_task.done():
                try:
                    self._current_asyncio_task.result()
                except Exception as e:
                    print(f"异步任务出错：{e}")
                # 返回 Panda3D 任务管理器的完成状态
                return panda3d_task.done  # 注意是 done 而不是 DONE
        # 返回 Panda3D 任务管理器的继续状态
        return panda3d_task.cont  # 注意是 cont 而不是 CONTINUE

    def _parse_tileset(self,tileset_data,tileset_info):
        try:
            root = tileset_data.get('root',{})
            self._parse_tile(root,tileset_info['node'],tileset_info)
            print("✓ Tileset 解析完成")
        except Exception as e:
            print(f"✗ Tileset 解析出错: {e}")

    def _parse_tile(self, tile_data, parent_node, tileset_info):
        try:
            # 获取tileID
            tile_id = f"tile_{len(tileset_info['tiles'])}"
            print(f"创建tile节点: {tile_id}")
            # 创建tile节点
            tile_node = parent_node.attachNewNode(tile_id)

            tileset_info['tiles'][tile_id] = {
                'node': tile_node,
                'data': tile_data,
                'loaded': False
            }

            # 如果有内容，创建占位几何体
            if 'content' in tile_data:
                print(f"为tile {tile_id} 创建几何体")
                self._create_tile_geometry(tile_node)
            # 递归解析子tiles
            children = tile_data.get('children', [])
            print(f"Tile {tile_id} 有 {len(children)} 个子节点")
            for child_data in children:
                self._parse_tile(child_data, tile_node, tileset_info)
        except Exception as e:
            print(f"✗ Tile 解析出错: {e}")
            import traceback
            traceback.print_exc()

    def _create_tile_geometry(self,parent_node):
        """为 tile 创建占位几何体"""
        try:
            # 创建一个简单的立方体作为占位符
            from panda3d.core import GeomVertexFormat, GeomVertexData, GeomVertexWriter
            from panda3d.core import Geom, GeomTriangles, GeomNode

            format = GeomVertexFormat.getV3n3c4()
            vdata = GeomVertexData('tile_cube', format, Geom.UHStatic)

            vertex = GeomVertexWriter(vdata, 'vertex')
            normal = GeomVertexWriter(vdata, 'normal')
            color = GeomVertexWriter(vdata, 'color')

            # 定义立方体顶点
            vertices = [
                (-0.5, -0.5, -0.5), (0.5, -0.5, -0.5), (0.5, 0.5, -0.5), (-0.5, 0.5, -0.5),
                (-0.5, -0.5, 0.5), (0.5, -0.5, 0.5), (0.5, 0.5, 0.5), (-0.5, 0.5, 0.5)
            ]

            for vert in vertices:
                vertex.addData3f(*vert)
                normal.addData3f(0, 0, 1)
                color.addData4f(0.2, 0.6, 0.8, 1.0)

            # 创建几何体
            geom = Geom(vdata)

            # 创建面
            prim = GeomTriangles(Geom.UHStatic)
            # 底面
            prim.addVertices(0, 1, 2)
            prim.addVertices(0, 2, 3)
            # 顶面
            prim.addVertices(4, 7, 6)
            prim.addVertices(4, 6, 5)
            # 前面
            prim.addVertices(0, 4, 5)
            prim.addVertices(0, 5, 1)
            # 后面
            prim.addVertices(2, 6, 7)
            prim.addVertices(2, 7, 3)
            # 左面
            prim.addVertices(0, 3, 7)
            prim.addVertices(0, 7, 4)
            # 右面
            prim.addVertices(1, 5, 6)
            prim.addVertices(1, 6, 2)

            prim.closePrimitive()
            geom.addPrimitive(prim)

            # 创建几何节点
            geom_node = GeomNode('tile_geometry')
            geom_node.addGeom(geom)

            # 添加到场景
            cube_node = parent_node.attachNewNode(geom_node)
            cube_node.setScale(1000)  # 放大以便观察

            # 添加材质
            material = Material()
            material.setBaseColor((0.2, 0.6, 0.8, 1.0))
            material.setSpecular((0.1, 0.1, 0.1, 1.0))
            material.setShininess(10.0)
            cube_node.setMaterial(material)

        except Exception as e:
            print(f"✗ 创建 tile 几何体出错: {e}")

    def _create_placeholder_geometry(self, parent_node):
        """创建一个简单的占位符几何体，让用户能看到节点"""
        try:
            from panda3d.core import GeomVertexFormat, GeomVertexData, GeomVertexWriter
            from panda3d.core import Geom, GeomTriangles, GeomNode

            # 创建简单的立方体作为占位符
            format = GeomVertexFormat.getV3n3c4()
            vdata = GeomVertexData('placeholder_cube', format, Geom.UHStatic)

            vertex = GeomVertexWriter(vdata, 'vertex')
            normal = GeomVertexWriter(vdata, 'normal')
            color = GeomVertexWriter(vdata, 'color')

            # 定义立方体顶点
            size = 1.0
            vertices = [
                # 前面 (Z+)
                (-size, -size, size), (size, -size, size), (size, size, size), (-size, size, size),
                # 后面 (Z-)
                (-size, -size, -size), (-size, size, -size), (size, size, -size), (size, -size, -size),
                # 左面 (X-)
                (-size, -size, -size), (-size, -size, size), (-size, size, size), (-size, size, -size),
                # 右面 (X+)
                (size, -size, -size), (size, size, -size), (size, size, size), (size, -size, size),
                # 上面 (Y+)
                (-size, size, -size), (-size, size, size), (size, size, size), (size, size, -size),
                # 下面 (Y-)
                (-size, -size, -size), (size, -size, -size), (size, -size, size), (-size, -size, size)
            ]

            normals = [
                # 前面法线
                (0, 0, 1), (0, 0, 1), (0, 0, 1), (0, 0, 1),
                # 后面法线
                (0, 0, -1), (0, 0, -1), (0, 0, -1), (0, 0, -1),
                # 左面法线
                (-1, 0, 0), (-1, 0, 0), (-1, 0, 0), (-1, 0, 0),
                # 右面法线
                (1, 0, 0), (1, 0, 0), (1, 0, 0), (1, 0, 0),
                # 上面法线
                (0, 1, 0), (0, 1, 0), (0, 1, 0), (0, 1, 0),
                # 下面法线
                (0, -1, 0), (0, -1, 0), (0, -1, 0), (0, -1, 0)
            ]

            # 青色
            face_colors = [
                (0.0, 1.0, 1.0, 1.0), (0.0, 1.0, 1.0, 1.0), (0.0, 1.0, 1.0, 1.0), (0.0, 1.0, 1.0, 1.0),  # 前面 - 青色
                (0.0, 0.8, 0.8, 1.0), (0.0, 0.8, 0.8, 1.0), (0.0, 0.8, 0.8, 1.0), (0.0, 0.8, 0.8, 1.0),  # 后面 - 稍暗青色
                (0.0, 0.9, 0.9, 1.0), (0.0, 0.9, 0.9, 1.0), (0.0, 0.9, 0.9, 1.0), (0.0, 0.9, 0.9, 1.0),  # 左面 - 中等青色
                (0.0, 0.7, 0.7, 1.0), (0.0, 0.7, 0.7, 1.0), (0.0, 0.7, 0.7, 1.0), (0.0, 0.7, 0.7, 1.0),  # 右面 - 稍暗青色
                (0.0, 1.0, 1.0, 1.0), (0.0, 1.0, 1.0, 1.0), (0.0, 1.0, 1.0, 1.0), (0.0, 1.0, 1.0, 1.0),  # 上面 - 青色
                (0.0, 0.6, 0.6, 1.0), (0.0, 0.6, 0.6, 1.0), (0.0, 0.6, 0.6, 1.0), (0.0, 0.6, 0.6, 1.0)  # 下面 - 更暗青色
            ]

            for i, vert in enumerate(vertices):
                vertex.addData3f(*vert)
                normal.addData3f(*normals[i])
                color.addData4f(*face_colors[i])

            # 创建几何体
            geom = Geom(vdata)

            # 创建面（每个面两个三角形）
            prim = GeomTriangles(Geom.UHStatic)

            # 每个面4个顶点，生成2个三角形
            for face in range(6):  # 6个面
                base_index = face * 4
                # 第一个三角形
                prim.addVertices(base_index, base_index + 1, base_index + 2)
                # 第二个三角形
                prim.addVertices(base_index, base_index + 2, base_index + 3)

            prim.closePrimitive()
            geom.addPrimitive(prim)

            # 创建几何节点
            geom_node = GeomNode('tileset_placeholder')
            geom_node.addGeom(geom)

            # 添加到场景
            cube_node = parent_node.attachNewNode(geom_node)
            cube_node.setScale(5)  # 设置合适的大小

            # 设置双面渲染
            cube_node.setTwoSided(True)

            # 添加材质
            material = Material()
            material.setBaseColor((0.0, 1.0, 1.0, 1.0))  # 青色
            material.setSpecular((0.5, 0.5, 0.5, 1.0))
            material.setShininess(32.0)
            cube_node.setMaterial(material)

            # 添加标识标签
            cube_node.setTag("element_type", "cesium_placeholder")

            print("✓ 占位符几何体创建完成")
            return cube_node
        except Exception as e:
            print(f"✗ 创建占位符几何体出错: {e}")
            import traceback
            traceback.print_exc()
            return None
