import { _decorator, Vec3 } from 'cc';
import { Direction, GridType } from '../core/Define';
import { EventManager, EventType } from '../core/EventManager';
import { JsBridge } from '../bridge/JsBridge';
import { GameManager } from '../manager/GameManager';
import { scaledMoveSpeed, UNITY_VEHICLE_MOVE_SPEED } from '../core/GridConstants';
import { Movement } from '../gameplay/Movement';
import { PlayerController, ExternalDataList } from './PlayerController';
import { syncRidePositions } from './RideLink';
import { VisualAssets } from '../visual/VisualAssets';

const { ccclass } = _decorator;

/**
 * 载具移动（对齐 Unity VehicleController）
 * - 仅能在空地移动（None↔None、Ride→None）
 * - 有骑手时每帧同步玩家；落格更新 Ride 注册
 */
@ccclass('VehicleController')
export class VehicleController extends Movement {
    private player: PlayerController | null = null;

    onLoad() {
        this.moverRole = 'vehicle';
        this.moveSpeed = scaledMoveSpeed(UNITY_VEHICLE_MOVE_SPEED);
        this.moveState = 0;
    }

    /** 不调用 super.start()，避免 component.start 晚于 LevelInit 绑定后再次用 spawn 方向刷贴图 */
    start() {
        this.syncCommittedCellFromPosition();
        if (this.player) {
            this.syncFacingFromRider();
        }
        this.setIcon();
    }

    setPlayer(p: PlayerController | null) {
        this.player = p;
        if (!p) return;
        if (p.direction !== this.direction) {
            super.setDirection(p.direction);
        }
        this.setIcon();
    }

    getPlayer(): PlayerController | null {
        return this.player;
    }

    setPosition(pos: Vec3) {
        this.node.setPosition(pos);
    }

    setName(_name: string) {
        /* 可挂 Label */
    }

    override setDirection(dir: Direction) {
        super.setDirection(dir);
        this.setIcon();
        if (Movement.callEach) return;
        Movement.callEach = true;
        this.player?.setDirection(dir);
        Movement.callEach = false;
    }

    private entityVisualOptions() {
        const gm = GameManager.instance;
        const levelTheme = gm?.getCurLevel()?.theme?.trim();
        return {
            ...(gm?.getEntityVisualOptions() ?? {}),
            theme: levelTheme ?? gm?.uiStyle ?? 'default',
        };
    }

    /** 载具四向贴图：有骑手时跟随骑手 direction，转向时 setIcon 直接换图 */
    private iconDirection(): Direction {
        return this.player?.direction ?? this.direction;
    }

    setIcon() {
        const dir = this.iconDirection();
        if (this.player && dir !== this.direction) {
            super.setDirection(dir);
        }
        VisualAssets.applyVehicleIconForDirection(
            this.node,
            dir,
            this.entityVisualOptions(),
        );
        this.player?.syncRideMountVisual();
    }

    /** 骑乘时逻辑朝向与骑手保持一致（Scratch 回传等） */
    private syncFacingFromRider() {
        if (!this.player || this.player.direction === this.direction) return;
        super.setDirection(this.player.direction);
    }

    /** 主题 / 软重置后按当前逻辑朝向重刷贴图 */
    refreshIcon() {
        this.syncFacingFromRider();
        this.setIcon();
    }

    override callJump() {
        /* 载具不可跳跃 */
    }

    protected override syncRideAfterMoveStep() {
        if (this.player) syncRidePositions('vehicle', this.player, this);
    }

    protected onMoveNextSet(isJump: boolean) {
        if (Movement.callEach) return;
        Movement.callEach = true;
        if (this.player) {
            this.player.setTargetGridType(this.targetGridType);
            this.player.syncFromVehicle(this.targetGridType, isJump);
        }
        Movement.callEach = false;
    }

    protected onMoving() {
        if (this.player) syncRidePositions('vehicle', this.player, this);
        if (Movement.callEach) return;
        Movement.callEach = true;
        this.player?.onMoving();
        Movement.callEach = false;
    }

    protected onMoveToTarget() {
        this.commitLandingCell();
        const gm = GameManager.instance!;
        gm.removeObj(this.lastPosition);
        if (this.committedCell) {
            gm.addObjAtCell(this.committedCell, GridType.Ride, this.node);
        } else {
            gm.addObj(this.node.position, GridType.Ride, this.node);
        }

        if (!Movement.callEach && this.player) {
            Movement.callEach = true;
            this.player.setRideBaseFromVehicle(this.node.position);
            if (this.committedCell) this.player.shareCommittedCell(this.committedCell);
            this.player.syncMoveToTargetFromVehicle();
            Movement.callEach = false;
        }

        if (this.step === 0) this.externalCall();
    }

    protected onMoveFail(_isJump: boolean) {
        this.externalCall();
        EventManager.dispatch(EventType.InputEnd, GameManager.instance!.gameState);
    }

    callVehicleInfo() {
        this.externalCall();
    }

    externalCall() {
        const gm = GameManager.instance!;
        const list: ExternalDataList = { direction: this.direction, externalDatas: [] };
        const sample = this.getGridSamplePosition();
        const self = gm.worldToCell(sample);
        list.externalDatas.push({
            position: { x: self.x, y: self.y, z: 0 },
            gridType: this.curGrid,
            direction: 'self',
        });
        for (let d = Direction.North; d <= Direction.West; d++) {
            const wp = gm.nextGridPosition(sample, d);
            const cell = gm.worldToCell(wp);
            list.externalDatas.push({
                position: { x: cell.x, y: cell.y, z: 0 },
                gridType: gm.calculateNextGridType(sample, d),
                direction: gm.getRelativePosition(this.direction, d),
            });
        }
        JsBridge.call('processVehicleData', JSON.stringify(list));
    }
}
