
import { Mesh } from "three";

import { Gizmos } from "../engine/engine_gizmos.js";
import { syncDestroy } from "../engine/engine_networking_instantiate.js";
import { getParam } from "../engine/engine_utils.js";
import { BoxHelperComponent } from "./BoxHelperComponent.js";
import { Behaviour, GameObject } from "./Component.js";
import { UsageMarker } from "./Interactable.js";

const debug = getParam("debugdeletable");
/**
 * The [DeleteBox](https://engine.needle.tools/docs/api/DeleteBox) component creates an invisible deletion zone that destroys objects entering it.
 * Works with objects that have a {@link Deletable} component attached.  
 * 
 * ![](https://cloud.needle.tools/-/media/J-Gmdhl214kfdjkfYViG8g.gif)
 *
 * **Use cases:**
 * - Trash bins in sandbox builders
 * - Kill zones in physics simulations
 * - Cleanup areas for multiplayer scenes
 *
 * **Setup:**
 * 1. Add DeleteBox to a GameObject with a BoxCollider-like shape
 * 2. Add {@link Deletable} component to objects that should be destroyable
 * 3. Objects entering the box will be destroyed (synced across network)
 *
 * **Debug:** Use `?debugdeletable` URL parameter to visualize deletion areas.
 *
 * - Example: https://engine.needle.tools/samples/collaborative-sandbox
 *
 * @example Create a deletion zone
 * ```ts
 * const trashBin = trashBinModel.addComponent(DeleteBox);
 * // Objects with Deletable component will be destroyed when entering
 * ```
 *
 * @summary Box area that deletes objects entering it
 * @category Interactivity
 * @group Components
 * @see {@link Deletable} - Add to objects that can be destroyed
 * @see {@link Duplicatable} for spawning objects
 * @see {@link DragControls} for moving objects
 */
export class DeleteBox extends BoxHelperComponent {
    static _instances: DeleteBox[] = [];
    
    onEnable(): void {
        DeleteBox._instances.push(this);
    }

    onDisable(): void {
        const idx = DeleteBox._instances.indexOf(this);
        if (idx >= 0) DeleteBox._instances.splice(idx, 1);
    }
}

/**
 * Marks a GameObject as deletable by {@link DeleteBox} zones.
 * Objects with this component will be destroyed (and synced across network)
 * when they enter a DeleteBox area.
 *
 * **Note:** Objects currently being used (with {@link UsageMarker}) are protected from deletion.
 *
 * @example Make an object deletable
 * ```ts
 * const deletable = spawnedObject.addComponent(Deletable);
 * // Object can now be destroyed by entering a DeleteBox
 * ```
 *
 * @summary Marks object as destroyable by DeleteBox
 * @category Interactivity
 * @group Components
 * @see {@link DeleteBox} for the deletion trigger
 * @see {@link UsageMarker} for protecting objects in use
 */
export class Deletable extends Behaviour {

    update(): void {
        for (const box of DeleteBox._instances) {
            const obj = this.gameObject as unknown as Mesh;
            const res = box.isInBox(obj);
            if (res === true) {
                const marker = GameObject.getComponentInParent(this.gameObject, UsageMarker);
                if (!marker) {
                    if (debug) {
                        try {
                            if (box["box"]) {
                                const deleteBoxArea = box["box"];
                                const deletedObjectArea = BoxHelperComponent["testBox"];
                                Gizmos.DrawWireBox3(deleteBoxArea, 0xff0000, 5);
                                Gizmos.DrawWireBox3(deletedObjectArea, 0x0000ff, 5);
                                console.log("DeleteBox: Destroying", this.gameObject, { deleteBoxArea, deletedObjectArea });
                            }
                            else {
                                console.log("DeleteBox: Destroying", this.gameObject);
                            }
                        } catch (_e) {}
                    }
                    syncDestroy(this.gameObject, this.context.connection);
                }
                else if (debug) console.warn("DeleteBox: Not deleting object with usage marker", this.guid, marker)
            }
        }
    }
}