bl_info = {
    "name": "TSDE Host Mini",
    "author": "Benjamin",
    "version": (1, 0, 0),
    "blender": (3, 0, 0),
    "location": "3D View > Sidebar > TSDE",
    "description": "TSDE Walk/Fly Recorder",
    "category": "3D View"
}

import bpy
from mathutils import Vector, Matrix

# Speicher für Recorder
RECORDER_POINTS = []
RECORDER_LENS_POINTS = []


# ---------------------------------------------------------
# Hilfsfunktionen
# ---------------------------------------------------------
def get_viewport_camera_position(context):
    """Holt die aktuelle Viewport-Position (wo der Nutzer wirklich ist)"""
    for area in context.screen.areas:
        if area.type == 'VIEW_3D':
            for space in area.spaces:
                if space.type == 'VIEW_3D':
                    # Viewport-Region finden
                    for region in area.regions:
                        if region.type == 'WINDOW':
                            # 3D-View Region
                            override = {'area': area, 'region': region, 'scene': context.scene, 'window': context.window}
                            rv3d = space.region_3d
                            if rv3d:
                                # Position und Rotation des Viewports
                                view_matrix = rv3d.view_matrix.inverted()
                                position = view_matrix.translation
                                return position
    return None

def set_camera_to_viewport(context):
    """Setzt die Kamera auf die aktuelle Viewport-Position"""
    pos = get_viewport_camera_position(context)
    if pos and context.scene.camera:
        context.scene.camera.location = pos
        
        # Auch Rotation setzen (optional)
        for area in context.screen.areas:
            if area.type == 'VIEW_3D':
                for space in area.spaces:
                    if space.type == 'VIEW_3D':
                        rv3d = space.region_3d
                        if rv3d:
                            context.scene.camera.rotation_euler = rv3d.view_rotation.to_euler()
                        break
                break
        return True
    return False

def get_lens_position(cam):
    """Berechnet die optische Linsenposition der Kamera"""
    cam_matrix = cam.matrix_world
    forward = cam_matrix.to_quaternion() @ Vector((0, 0, -1))
    lens_offset = cam.data.lens / (cam.data.sensor_width or 36.0)
    return cam_matrix.translation + forward * lens_offset


# ---------------------------------------------------------
# Walk/Fly starten
# ---------------------------------------------------------
class TSDE_OT_walkfly(bpy.types.Operator):
    bl_idname = "tsde.walkfly"
    bl_label = "Walk/Fly starten"
    bl_description = "Aktiviert den Walk/Fly Modus"

    def execute(self, context):
        bpy.ops.view3d.walk('INVOKE_DEFAULT')
        self.report({'INFO'}, "Walk/Fly Modus aktiv - WASD zum Bewegen, ESC zum beenden")
        return {'FINISHED'}


# ---------------------------------------------------------
# Viewport to Camera
# ---------------------------------------------------------
class TSDE_OT_viewport_to_camera(bpy.types.Operator):
    bl_idname = "tsde.viewport_to_camera"
    bl_label = "Viewport → Kamera"
    bl_description = "Setzt die Kamera auf die aktuelle Viewport-Position"

    def execute(self, context):
        if set_camera_to_viewport(context):
            self.report({'INFO'}, "Kamera auf Viewport-Position gesetzt")
        else:
            self.report({'ERROR'}, "Konnte Viewport-Position nicht ermitteln")
        return {'FINISHED'}


# ---------------------------------------------------------
# Modal Recorder
# ---------------------------------------------------------
class TSDE_OT_record_modal(bpy.types.Operator):
    bl_idname = "tsde.record_modal"
    bl_label = "1. Recording starten"
    bl_description = "Zuerst Recording starten, DANN Walk/Fly"

    _timer = None
    recording = False
    frame_count = 0
    last_pos = None

    def modal(self, context, event):
        global RECORDER_POINTS, RECORDER_LENS_POINTS

        # ESC beendet das Recording
        if event.type == 'ESC':
            return self.finish(context)

        # Timer sammelt Positionen (20 FPS)
        if event.type == 'TIMER':
            cam = context.scene.camera
            
            # WICHTIG: Viewport-Position in Kamera übertragen
            set_camera_to_viewport(context)
            
            if cam:
                # Position mit Matrix World
                pos = cam.matrix_world.translation.copy()
                lens_pos = get_lens_position(cam)
                
                # Aufnehmen
                RECORDER_POINTS.append(pos)
                RECORDER_LENS_POINTS.append(lens_pos)
                self.frame_count += 1
                
                # Nur alle 10 Frames ausgeben
                if self.frame_count % 10 == 0:
                    print(f"🎥 Aufgenommen: {self.frame_count} Frames - Position: ({pos.x:.2f}, {pos.y:.2f}, {pos.z:.2f})")
                
                # Viewport updaten
                if context.area:
                    context.area.tag_redraw()

        return {'PASS_THROUGH'}

    def execute(self, context):
        global RECORDER_POINTS, RECORDER_LENS_POINTS
        RECORDER_POINTS = []
        RECORDER_LENS_POINTS = []
        self.frame_count = 0
        self.last_pos = None
        self.recording = True

        # Timer mit 20 FPS
        wm = context.window_manager
        self._timer = wm.event_timer_add(0.05, window=context.window)
        wm.modal_handler_add(self)

        print("\n" + "="*60)
        print("🎬 1. RECORDING GESTARTET")
        print("="*60)
        print("👉 JETZT: 'Walk/Fly starten' klicken")
        print("👉 Im Walk/Fly Modus bewegen")
        print("👉 Walk/Fly mit ESC beenden")
        print("👉 NOCHMAL ESC für Recording-Stop")
        print("="*60 + "\n")
        
        self.report({'INFO'}, "Recording läuft - JETZT Walk/Fly starten!")
        return {'RUNNING_MODAL'}

    def finish(self, context):
        self.recording = False
        wm = context.window_manager
        wm.event_timer_remove(self._timer)

        count = len(RECORDER_POINTS)
        lens_count = len(RECORDER_LENS_POINTS)
        
        print(f"\n📊 Recording beendet.")
        print(f"   Pivot-Frames: {count}")
        print(f"   Lens-Frames:  {lens_count}")

        if count < 2:
            self.report({'WARNING'}, "Zu wenig Frames! (min. 2 benötigt)")
            return {'CANCELLED'}

        # Pivot-Spline erzeugen
        pivot_curve = bpy.data.curves.new("Pivot_Spline", type='CURVE')
        pivot_curve.dimensions = '3D'
        pivot_spline = pivot_curve.splines.new('POLY')
        pivot_spline.points.add(count - 1)

        for i, p in enumerate(RECORDER_POINTS):
            pivot_spline.points[i].co = (p.x, p.y, p.z, 1.0)

        pivot_obj = bpy.data.objects.new("Pivot_Spline", pivot_curve)
        if hasattr(pivot_obj, "color"):
            pivot_obj.color = (1.0, 0.5, 0.0, 1.0)  # Orange
        context.scene.collection.objects.link(pivot_obj)

        # Lens-Spline erzeugen
        lens_curve = bpy.data.curves.new("Lens_Spline", type='CURVE')
        lens_curve.dimensions = '3D'
        lens_spline = lens_curve.splines.new('POLY')
        lens_spline.points.add(lens_count - 1)

        for i, p in enumerate(RECORDER_LENS_POINTS):
            lens_spline.points[i].co = (p.x, p.y, p.z, 1.0)

        lens_obj = bpy.data.objects.new("Lens_Spline", lens_curve)
        if hasattr(lens_obj, "color"):
            lens_obj.color = (0.0, 0.8, 1.0, 1.0)  # Hellblau
        context.scene.collection.objects.link(lens_obj)

        print(f"\n✅ Pivot-Spline erzeugt: {pivot_obj.name} ({count} Punkte)")
        print(f"✅ Lens-Spline erzeugt: {lens_obj.name} ({lens_count} Punkte)")
        
        self.report({'INFO'}, f"Splines erzeugt mit {count} Punkten!")
        return {'FINISHED'}


# ---------------------------------------------------------
# Panel
# ---------------------------------------------------------
class TSDE_PT_panel(bpy.types.Panel):
    bl_label = "TSDE Mini Host"
    bl_idname = "TSDE_PT_panel"
    bl_space_type = 'VIEW_3D'
    bl_region_type = 'UI'
    bl_category = 'TSDE'

    def draw(self, context):
        layout = self.layout
        box = layout.box()
        col = box.column(align=True)
        
        # REIHENFOLGE
        col.label(text="🔴 RICHTIGE REIHENFOLGE:", icon='INFO')
        col.separator()
        
        # 1. Recording starten
        col.scale_y = 1.3
        col.operator("tsde.record_modal", text="1. 🎥 RECORDING STARTEN", icon='REC')
        
        col.separator()
        
        # 2. Walk/Fly starten
        col.scale_y = 1.3
        col.operator("tsde.walkfly", text="2. 🚶 WALK/FLY STARTEN", icon='VIEW3D')
        
        col.separator()
        
        # 3. Optional: Viewport to Camera (manuell)
        col.operator("tsde.viewport_to_camera", text="3. Viewport → Kamera", icon='CAMERA_DATA')
        
        col.separator()
        
        # Status
        if len(RECORDER_POINTS) > 0:
            box = layout.box()
            col = box.column(align=True)
            col.label(text="📊 STATUS:", icon='INFO')
            col.label(text=f"Frames: {len(RECORDER_POINTS)}")
            
            if len(RECORDER_POINTS) > 0:
                last = RECORDER_POINTS[-1]
                col.label(text=f"Letzte: ({last.x:.1f}, {last.y:.1f}, {last.z:.1f})")
        
        # Anleitung
        box = layout.box()
        col = box.column(align=True)
        col.label(text="📝 ANLEITUNG:", icon='TEXT')
        col.label(text="1. 'RECORDING STARTEN' klicken")
        col.label(text="2. 'WALK/FLY STARTEN' klicken")
        col.label(text="3. Im Walk/Fly Modus bewegen")
        col.label(text="4. ESC (beendet Walk/Fly)")
        col.label(text="5. ESC (beendet Recording)")
        col.label(text="6. Splines werden automatisch erzeugt")


# ---------------------------------------------------------
# Registration
# ---------------------------------------------------------
classes = (
    TSDE_OT_record_modal,
    TSDE_OT_walkfly,
    TSDE_OT_viewport_to_camera,
    TSDE_PT_panel,
)

def register():
    for c in classes:
        try:
            bpy.utils.register_class(c)
        except:
            bpy.utils.unregister_class(c)
            bpy.utils.register_class(c)
    
    print("\n" + "="*60)
    print("🎥 TSDE MINI HOST GELADEN (mit Viewport-Tracking)")
    print("="*60)
    print("🔴 WICHTIG: Jetzt wird die VIEWPORT-Position aufgenommen!")
    print("="*60 + "\n")

def unregister():
    for c in reversed(classes):
        try:
            bpy.utils.unregister_class(c)
        except:
            pass
    
    print("TSDE Mini Host ENTLADEN")

if __name__ == "__main__":
    register()