export class Vector {
    constructor(x, y, z) {
        this.x = x;
        this.y = y;
        this.z = z;
    }

    static equals(x, y) {
        return x.x === y.x && x.y === y.y && x.z === y.z;
    }

    length() {
        return Math.sqrt(this.x * this.x + this.y * this.y + this.z * this.z);
    }

    lengthSquared() {
        return this.x * this.x + this.y * this.y + this.z * this.z;
    }

    normalized() {
        return Vector.divideScalar(this, this.length() || 1);
    }

    static add(a, b) {
        return new Vector(a.x + b.x, a.y + b.y, a.z + b.z);
    }

    static cross(a, b) {
        return new Vector(
            a.y * b.z - a.z * b.y,
            a.z * b.x - a.x * b.z,
            a.x * b.y - a.y * b.x
        );
    }

    static distance(a, b) {
        return Math.sqrt(this.distanceSquared(a, b));
    }

    static distanceSquared(a, b) {
        const dx = a.x - b.x;
        const dy = a.y - b.y;
        const dz = a.z - b.z;
        return dx * dx + dy * dy + dz * dz;
    }

    static divide(a, b) {
        return new Vector(a.x / b.x, a.y / b.y, a.z / b.z);
    }

    static divideScalar(a, scalar) {
        return this.multiplyScalar(a, 1 / scalar);
    }

    static dot(a, b) {
        return a.x * b.x + a.y * b.y + a.z * b.z;
    }

    static lerp(a, b, t) {
        return new Vector(
            a.x + (b.x - a.x) * t,
            a.y + (b.y - a.y) * t,
            a.z + (b.z - a.z) * t
        );
    }

    static max(a, b) {
        return new Vector(Math.max(a.x, b.x), Math.max(a.y, b.y), Math.max(a.z, b.z));
    }

    static min(a, b) {
        return new Vector(Math.min(a.x, b.x), Math.min(a.y, b.y), Math.min(a.z, b.z));
    }

    static multiply(a, b) {
        return new Vector(a.x * b.x, a.y * b.y, a.z * b.z);
    }

    static multiplyScalar(a, scalar) {
        return new Vector(a.x * scalar, a.y * scalar, a.z * scalar);
    }

    static subtract(a, b) {
        return new Vector(a.x - b.x, a.y - b.y, a.z - b.z);
    }

    static centeredXZ(a) {
        return new Vector(Math.floor(a.x) + 0.5, a.y, Math.floor(a.z) + 0.5);
    }

    toString() {
        return `${this.x} ${this.y} ${this.z}`;
    }
}

Vector.back = new Vector(0, 0, -1);
Vector.down = new Vector(0, -1, 0);
Vector.forward = new Vector(0, 0, 1);
Vector.left = new Vector(-1, 0, 0);
Vector.one = new Vector(1, 1, 1);
Vector.right = new Vector(1, 0, 0);
Vector.up = new Vector(0, 1, 0);
Vector.zero = new Vector(0, 0, 0);
