/**
 * Physics 2D Gizmo Implementation
 * 2D 物理 Gizmo 实现
 *
 * 使用 GizmoRegistry 为物理组件注册 gizmo 提供者。
 * 通过 Rust WebGL 引擎渲染。
 */

import type { Entity } from '@esengine/ecs-framework';
import type {
    IGizmoRenderData,
    IRectGizmoData,
    ICircleGizmoData,
    ILineGizmoData,
    ICapsuleGizmoData,
    GizmoColor
} from '@esengine/editor-core';
import { GizmoRegistry } from '@esengine/editor-core';
import { TransformComponent } from '@esengine/ecs-components';

import { BoxCollider2DComponent } from '../../components/BoxCollider2DComponent';
import { CircleCollider2DComponent } from '../../components/CircleCollider2DComponent';
import { CapsuleCollider2DComponent } from '../../components/CapsuleCollider2DComponent';
import { PolygonCollider2DComponent } from '../../components/PolygonCollider2DComponent';
import { Rigidbody2DComponent } from '../../components/Rigidbody2DComponent';
import { RigidbodyType2D } from '../../types/Physics2DTypes';

/**
 * 物理 Gizmo 颜色配置
 */
const PhysicsGizmoColors = {
    collider: { r: 0.0, g: 0.8, b: 0.0, a: 1.0 } as GizmoColor,
    trigger: { r: 1.0, g: 0.6, b: 0.0, a: 1.0 } as GizmoColor,
    selected: { r: 0.0, g: 1.0, b: 1.0, a: 1.0 } as GizmoColor,
    dynamicBody: { r: 0.2, g: 0.6, b: 1.0, a: 0.9 } as GizmoColor,
    kinematicBody: { r: 0.8, g: 0.3, b: 1.0, a: 0.9 } as GizmoColor,
    staticBody: { r: 0.5, g: 0.5, b: 0.5, a: 0.7 } as GizmoColor,
    velocity: { r: 1.0, g: 0.2, b: 0.2, a: 0.9 } as GizmoColor,
    centerMark: { r: 1.0, g: 1.0, b: 1.0, a: 0.8 } as GizmoColor,
};

/**
 * 获取碰撞体 Gizmo 颜色
 */
function getColliderColor(isSelected: boolean, isTrigger: boolean): GizmoColor {
    if (isSelected) {
        return PhysicsGizmoColors.selected;
    }
    if (isTrigger) {
        return PhysicsGizmoColors.trigger;
    }
    return PhysicsGizmoColors.collider;
}

/**
 * 获取刚体类型颜色
 */
function getRigidbodyColor(bodyType: RigidbodyType2D, isSelected: boolean): GizmoColor {
    const baseAlpha = isSelected ? 1.0 : 0.7;

    switch (bodyType) {
        case RigidbodyType2D.Dynamic:
            return { ...PhysicsGizmoColors.dynamicBody, a: baseAlpha };
        case RigidbodyType2D.Kinematic:
            return { ...PhysicsGizmoColors.kinematicBody, a: baseAlpha };
        case RigidbodyType2D.Static:
            return { ...PhysicsGizmoColors.staticBody, a: baseAlpha };
        default:
            return { r: 1, g: 1, b: 1, a: baseAlpha };
    }
}

/**
 * 创建中心点标记 Gizmo (十字形)
 */
function createCenterMarkGizmo(x: number, y: number, size: number, color: GizmoColor): ILineGizmoData[] {
    const halfSize = size / 2;
    return [
        {
            type: 'line',
            points: [
                { x: x - halfSize, y: y },
                { x: x + halfSize, y: y }
            ],
            color,
            closed: false
        },
        {
            type: 'line',
            points: [
                { x: x, y: y - halfSize },
                { x: x, y: y + halfSize }
            ],
            color,
            closed: false
        }
    ];
}

/**
 * BoxCollider2D gizmo provider
 * 矩形碰撞体 gizmo 提供者
 */
function boxCollider2DGizmoProvider(
    collider: BoxCollider2DComponent,
    entity: Entity,
    isSelected: boolean
): IGizmoRenderData[] {
    const transform = entity.getComponent(TransformComponent);
    if (!transform) return [];

    const gizmos: IGizmoRenderData[] = [];
    const color = getColliderColor(isSelected, collider.isTrigger);

    const rotation = typeof transform.rotation === 'number'
        ? transform.rotation
        : transform.rotation.z;

    const worldX = transform.position.x + collider.offset.x * transform.scale.x;
    const worldY = transform.position.y + collider.offset.y * transform.scale.y;
    const scaledWidth = collider.width * transform.scale.x;
    const scaledHeight = collider.height * transform.scale.y;
    const totalRotation = rotation + collider.rotationOffset;

    // 主要矩形边框
    const rectGizmo: IRectGizmoData = {
        type: 'rect',
        x: worldX,
        y: worldY,
        width: scaledWidth,
        height: scaledHeight,
        rotation: totalRotation,
        originX: 0.5,
        originY: 0.5,
        color,
        showHandles: false
    };
    gizmos.push(rectGizmo);

    // 选中时显示中心点标记
    if (isSelected) {
        const centerMarkSize = Math.min(scaledWidth, scaledHeight) * 0.1;
        gizmos.push(...createCenterMarkGizmo(worldX, worldY, centerMarkSize, PhysicsGizmoColors.centerMark));
    }

    return gizmos;
}

/**
 * CircleCollider2D gizmo provider
 * 圆形碰撞体 gizmo 提供者
 */
function circleCollider2DGizmoProvider(
    collider: CircleCollider2DComponent,
    entity: Entity,
    isSelected: boolean
): IGizmoRenderData[] {
    const transform = entity.getComponent(TransformComponent);
    if (!transform) return [];

    const gizmos: IGizmoRenderData[] = [];
    const color = getColliderColor(isSelected, collider.isTrigger);

    const worldX = transform.position.x + collider.offset.x * transform.scale.x;
    const worldY = transform.position.y + collider.offset.y * transform.scale.y;
    const scale = Math.max(Math.abs(transform.scale.x), Math.abs(transform.scale.y));
    const scaledRadius = collider.radius * scale;

    // 主要圆形边框
    const circleGizmo: ICircleGizmoData = {
        type: 'circle',
        x: worldX,
        y: worldY,
        radius: scaledRadius,
        color
    };
    gizmos.push(circleGizmo);

    // 选中时显示额外信息
    if (isSelected) {
        // 中心点标记
        const centerMarkSize = scaledRadius * 0.15;
        gizmos.push(...createCenterMarkGizmo(worldX, worldY, centerMarkSize, PhysicsGizmoColors.centerMark));

        // 半径指示线 (从中心到右边缘)
        const rotation = typeof transform.rotation === 'number'
            ? transform.rotation
            : transform.rotation.z;
        const cos = Math.cos(rotation);
        const sin = Math.sin(rotation);

        gizmos.push({
            type: 'line',
            points: [
                { x: worldX, y: worldY },
                { x: worldX + scaledRadius * cos, y: worldY + scaledRadius * sin }
            ],
            color: PhysicsGizmoColors.selected,
            closed: false
        } as ILineGizmoData);

        // 边缘小圆点
        gizmos.push({
            type: 'circle',
            x: worldX + scaledRadius * cos,
            y: worldY + scaledRadius * sin,
            radius: scaledRadius * 0.08,
            color: PhysicsGizmoColors.selected
        } as ICircleGizmoData);
    }

    return gizmos;
}

/**
 * CapsuleCollider2D gizmo provider
 * 胶囊碰撞体 gizmo 提供者
 */
function capsuleCollider2DGizmoProvider(
    collider: CapsuleCollider2DComponent,
    entity: Entity,
    isSelected: boolean
): IGizmoRenderData[] {
    const transform = entity.getComponent(TransformComponent);
    if (!transform) return [];

    const gizmos: IGizmoRenderData[] = [];
    const color = getColliderColor(isSelected, collider.isTrigger);

    const rotation = typeof transform.rotation === 'number'
        ? transform.rotation
        : transform.rotation.z;
    const totalRotation = rotation + collider.rotationOffset;

    const worldX = transform.position.x + collider.offset.x * transform.scale.x;
    const worldY = transform.position.y + collider.offset.y * transform.scale.y;

    const radius = collider.radius * transform.scale.x;
    const halfHeight = collider.halfHeight * transform.scale.y;

    // 使用原生胶囊 Gizmo 类型
    gizmos.push({
        type: 'capsule',
        x: worldX,
        y: worldY,
        radius,
        halfHeight,
        rotation: totalRotation,
        color
    } as ICapsuleGizmoData);

    if (isSelected) {
        const centerMarkSize = radius * 0.15;
        gizmos.push(...createCenterMarkGizmo(worldX, worldY, centerMarkSize, PhysicsGizmoColors.centerMark));
    }

    return gizmos;
}

/**
 * PolygonCollider2D gizmo provider
 * 多边形碰撞体 gizmo 提供者
 */
function polygonCollider2DGizmoProvider(
    collider: PolygonCollider2DComponent,
    entity: Entity,
    isSelected: boolean
): IGizmoRenderData[] {
    const transform = entity.getComponent(TransformComponent);
    if (!transform) return [];

    if (collider.vertices.length < 3) return [];

    const gizmos: IGizmoRenderData[] = [];
    const color = getColliderColor(isSelected, collider.isTrigger);

    const rotation = typeof transform.rotation === 'number'
        ? transform.rotation
        : transform.rotation.z;
    const totalRotation = rotation + collider.rotationOffset;
    const cos = Math.cos(totalRotation);
    const sin = Math.sin(totalRotation);

    const worldX = transform.position.x + collider.offset.x * transform.scale.x;
    const worldY = transform.position.y + collider.offset.y * transform.scale.y;

    const worldPoints = collider.vertices.map(v => {
        const scaledX = v.x * transform.scale.x;
        const scaledY = v.y * transform.scale.y;
        const rotatedX = scaledX * cos - scaledY * sin;
        const rotatedY = scaledX * sin + scaledY * cos;
        return {
            x: worldX + rotatedX,
            y: worldY + rotatedY
        };
    });

    gizmos.push({
        type: 'line',
        points: worldPoints,
        color,
        closed: true
    } as ILineGizmoData);

    if (isSelected) {
        // 中心点标记
        const centerMarkSize = 0.5;
        gizmos.push(...createCenterMarkGizmo(worldX, worldY, centerMarkSize, PhysicsGizmoColors.centerMark));

        // 顶点标记
        const vertexSize = 0.15;
        for (const point of worldPoints) {
            gizmos.push({
                type: 'circle',
                x: point.x,
                y: point.y,
                radius: vertexSize,
                color: PhysicsGizmoColors.selected
            } as ICircleGizmoData);
        }
    }

    return gizmos;
}

/**
 * Rigidbody2D gizmo provider
 * 刚体 gizmo 提供者
 */
function rigidbody2DGizmoProvider(
    rigidbody: Rigidbody2DComponent,
    entity: Entity,
    isSelected: boolean
): IGizmoRenderData[] {
    const transform = entity.getComponent(TransformComponent);
    if (!transform) return [];

    const gizmos: IGizmoRenderData[] = [];
    const bodyColor = getRigidbodyColor(rigidbody.bodyType, isSelected);

    if (isSelected) {
        // 刚体类型标记
        gizmos.push({
            type: 'circle',
            x: transform.position.x,
            y: transform.position.y,
            radius: 0.3,
            color: bodyColor
        } as ICircleGizmoData);

        // 速度向量
        const velMagnitude = Math.sqrt(
            rigidbody.velocity.x * rigidbody.velocity.x +
            rigidbody.velocity.y * rigidbody.velocity.y
        );

        if (velMagnitude > 0.1) {
            const scale = 0.5;
            const endX = transform.position.x + rigidbody.velocity.x * scale;
            const endY = transform.position.y + rigidbody.velocity.y * scale;

            // 速度线
            gizmos.push({
                type: 'line',
                points: [
                    { x: transform.position.x, y: transform.position.y },
                    { x: endX, y: endY }
                ],
                color: PhysicsGizmoColors.velocity,
                closed: false
            } as ILineGizmoData);

            // 箭头
            const arrowSize = 0.3;
            const angle = Math.atan2(rigidbody.velocity.y, rigidbody.velocity.x);
            const arrowAngle = Math.PI / 6;

            gizmos.push({
                type: 'line',
                points: [
                    { x: endX, y: endY },
                    {
                        x: endX - arrowSize * Math.cos(angle - arrowAngle),
                        y: endY - arrowSize * Math.sin(angle - arrowAngle)
                    }
                ],
                color: PhysicsGizmoColors.velocity,
                closed: false
            } as ILineGizmoData);

            gizmos.push({
                type: 'line',
                points: [
                    { x: endX, y: endY },
                    {
                        x: endX - arrowSize * Math.cos(angle + arrowAngle),
                        y: endY - arrowSize * Math.sin(angle + arrowAngle)
                    }
                ],
                color: PhysicsGizmoColors.velocity,
                closed: false
            } as ILineGizmoData);
        }
    }

    return gizmos;
}

/**
 * Register gizmo providers for all physics components.
 * 为所有物理组件注册 gizmo 提供者。
 */
export function registerPhysics2DGizmos(): void {
    GizmoRegistry.register(BoxCollider2DComponent, boxCollider2DGizmoProvider);
    GizmoRegistry.register(CircleCollider2DComponent, circleCollider2DGizmoProvider);
    GizmoRegistry.register(CapsuleCollider2DComponent, capsuleCollider2DGizmoProvider);
    GizmoRegistry.register(PolygonCollider2DComponent, polygonCollider2DGizmoProvider);
    GizmoRegistry.register(Rigidbody2DComponent, rigidbody2DGizmoProvider);
}

/**
 * Unregister gizmo providers for all physics components.
 * 取消注册所有物理组件的 gizmo 提供者。
 */
export function unregisterPhysics2DGizmos(): void {
    GizmoRegistry.unregister(BoxCollider2DComponent);
    GizmoRegistry.unregister(CircleCollider2DComponent);
    GizmoRegistry.unregister(CapsuleCollider2DComponent);
    GizmoRegistry.unregister(PolygonCollider2DComponent);
    GizmoRegistry.unregister(Rigidbody2DComponent);
}
