import { Color } from "../../../../../core/color/Color.js";
import { computeConeBoundingBox } from "../../../../../core/geom/3d/cone/computeConeBoundingBox.js";
import Vector1 from "../../../../../core/geom/Vector1.js";
import Vector3 from "../../../../../core/geom/Vector3.js";
import { AbstractLight } from "./AbstractLight.js";

export class SpotLight extends AbstractLight {


    /**
     * @readonly
     * @type {Vector3}
     */
    position = new Vector3();

    /**
     * @readonly
     * @type {Vector3}
     */
    direction = new Vector3();

    /**
     * @readonly
     * @type {Vector1}
     */
    angle = new Vector1(Math.PI / 2);

    /**
     * @readonly
     * @type {Vector1}
     */
    distance = new Vector1(1);

    /**
     * @readonly
     * @type {Color}
     */
    color = new Color(1, 1, 1);

    /**
     * @readonly
     * @type {Vector1}
     */
    intensity = new Vector1(1);

    /**
     * @readonly
     * @type {Vector1}
     */
    penumbra = new Vector1(0.4);


    getCenter(result) {
        // find center of the cone (mid point along the cone length)

        const d = this.direction;

        const m = this.distance.getValue() * 0.5;

        const p = this.position;

        result[0] = p.x + d.x * m;
        result[1] = p.y + d.y * m;
        result[2] = p.z + d.z * m;
    }

    getAABB(result) {
        const position = this.position;
        const direction = this.direction;

        const angle = this.angle.getValue();
        const distance = this.distance.getValue();

        computeConeBoundingBox(
            result,
            position.x, position.y, position.z,
            direction.x, direction.y, direction.z,
            angle,
            distance
        );
    }

    onDimensionChanged(listener, context) {
        this.position.onChanged.add(listener, context);
        this.angle.onChanged.add(listener, context);
        this.distance.onChanged.add(listener, context);
        this.direction.onChanged.add(listener, context);
    }

    offDimensionChanged(listener, context) {
        this.position.onChanged.remove(listener, context);
        this.angle.onChanged.remove(listener, context);
        this.distance.onChanged.remove(listener, context);
        this.direction.onChanged.remove(listener, context);
    }

    /**
     *
     * @param {number[]|Float32Array|Float64Array} destination
     * @param {number} address
     * @returns {number} number of used slots
     */
    toArray(destination, address) {
        const position = this.position;

        destination[address] = position.x;
        destination[address + 1] = position.y;
        destination[address + 2] = position.z;

        // direction
        const direction = this.direction;

        destination[address + 3] = direction.x;
        destination[address + 4] = direction.y;
        destination[address + 5] = direction.z;

        destination[address + 6] = this.angle.getValue();

        destination[address + 7] = this.distance.getValue();

        const color = this.color;

        destination[address + 8] = color.r;
        destination[address + 9] = color.g;
        destination[address + 10] = color.b;

        destination[address + 11] = this.intensity.getValue();
        destination[address + 12] = this.penumbra.getValue();

        return 13;
    }
}

/**
 * @readonly
 * @type {boolean}
 */
SpotLight.prototype.isSpotLight = true;
