import { BoxHelper, Color, Object3D } from "three";

import * as params from "../engine/engine_default_parameters.js";
import * as Gizmos from "../engine/engine_gizmos.js";
import { serializable } from "../engine/engine_serialization_decorator.js";
import { FrameEvent } from "../engine/engine_setup.js";
import { Behaviour } from "./Component.js";

/**
 * BoxGizmo is a component that displays a box around the object in the scene. It can optionally expand to the object's bounds.
 *
 * @summary Display a box around the object
 * @category Helpers
 * @group Components
 */
export class BoxGizmo extends Behaviour {
    @serializable()
    objectBounds: boolean = false;
    @serializable(Color)
    color?: Color;
    @serializable()
    isGizmo : boolean = true;

    private _gizmoObject: Object3D | null | BoxHelper = null;
    private _boxHelper: BoxHelper | null = null;

    onEnable(): void {
        if (this.isGizmo && !params.showGizmos) return;
        if (!this._gizmoObject) {
            if (this.objectBounds) {
                this._gizmoObject = new BoxHelper(this.gameObject, this.color ?? 0xffff00);
            }
            else {
                this.objectBounds = false;
                this._gizmoObject = Gizmos.CreateWireCube(this.color ?? 0xffff00);
            }
        }
        if (this.objectBounds) {
            this.scene.add(this._gizmoObject);
            this._boxHelper = this._gizmoObject as BoxHelper;
            this.startCoroutine(this.syncObjectBounds(), FrameEvent.OnBeforeRender);
        }
        else
            this.gameObject.add(this._gizmoObject);
    }

    onDisable(): void {
        if (this._gizmoObject) {
            this.gameObject.remove(this._gizmoObject);
        }
    }

    private *syncObjectBounds() {
        while (this._boxHelper) {
            this._boxHelper?.update();
            yield;
        }
    }
}