import { degToRad } from "./calc";
export default class CustomVector3 {
    constructor(x, y, z) {
        this.x = x;
        this.y = y;
        this.z = z;
    }
    static createSphere(center, radius, amount, surface = false) {
        let positions = [];
        for (let i = 0; i < amount; i++) {
            // Random angles for spherical coordinates
            const theta = Math.random() * 2 * Math.PI; // Random angle in [0, 2PI]
            const phi = Math.acos(2 * Math.random() - 1); // Random angle in [0, PI]
            let r = radius;
            if (surface) {
                r *= Math.cbrt(Math.random()); // Random distance from the center to the surface
            }
            else {
                r *= Math.random(); // Random distance from the center to anywhere inside the sphere
            }
            // Convert spherical to Cartesian coordinates
            const x = center.x + r * Math.sin(phi) * Math.cos(theta);
            const y = center.y + r * Math.sin(phi) * Math.sin(theta);
            const z = center.z + r * Math.cos(phi);
            // Create a new vector for the position
            positions.push(new CustomVector3(x, y, z));
        }
        return positions;
    }
    static createCylinder(center, radius, height, amount, surface = false) {
        let positions = [];
        for (let i = 0; i < amount; i++) {
            // Random angle for cylindrical coordinates
            const theta = Math.random() * 2 * Math.PI; // Random angle in [0, 2PI]
            // Random height along the cylinder's vertical axis (y-axis)
            const y = center.y - height / 2 + Math.random() * height; // Random height in [center.y - height/2, center.y + height/2]
            // Determine the radius for this point
            const pointRadius = surface ? radius : Math.random() * radius;
            // Circle in the horizontal plane (x, z axes) with variable radius for volume distribution
            const x = center.x + pointRadius * Math.cos(theta); // Circular path around x-axis
            const z = center.z + pointRadius * Math.sin(theta); // Circular path around z-axis, perpendicular to the x-axis
            // Create a new vector for the position
            positions.push(new CustomVector3(x, y, z));
        }
        return positions;
    }
    static fromMC(vec3) {
        return new CustomVector3(vec3.x, vec3.y, vec3.z);
    }
    static randomWithinRadius(center, radius) {
        const randomAngle = Math.random() * 2 * Math.PI;
        const distance = Math.random() * radius;
        const x = center.x + Math.cos(randomAngle) * distance;
        const z = center.z + Math.sin(randomAngle) * distance;
        return new CustomVector3(x, center.y, z); // Keep the Y-value at player's height initially
    }
    distanceTo(other) {
        const dx = this.x - other.x;
        const dy = this.y - other.y;
        const dz = this.z - other.z;
        return Math.sqrt(dx * dx + dy * dy + dz * dz);
    }
    add(other) {
        return new CustomVector3(this.x + other.x, this.y + other.y, this.z + other.z);
    }
    subtract(other) {
        return new CustomVector3(this.x - other.x, this.y - other.y, this.z - other.z);
    }
    multiply(value) {
        return new CustomVector3(this.x * value, this.y * value, this.z * value);
    }
    length() {
        return Math.sqrt(this.x ** 2 + this.y ** 2 + this.z ** 2);
    }
    normalize() {
        const length = this.length();
        return new CustomVector3(this.x / length, this.y / length, this.z / length);
    }
    dot(other) {
        return this.x * other.x + this.y * other.y + this.z * other.z;
    }
    toMC() {
        return { x: this.x, y: this.y, z: this.z };
    }
    yOffset(offset) {
        return new CustomVector3(this.x, this.y + offset, this.z);
    }
    cross(other) {
        return new CustomVector3(this.y * other.z - this.z * other.y, this.z * other.x - this.x * other.z, this.x * other.y - this.y * other.x);
    }
    angleDegrees(other) {
        // cos(theta) = (A . B) / (|A| * |B|)
        const dot = this.dot(other);
        const lengthA = this.length();
        const lengthB = other.length();
        const cosTheta = dot / (lengthA * lengthB);
        const angle = Math.acos(cosTheta) * (180 / Math.PI);
        const cross = this.cross(other);
        if (cross.y < 0)
            return -angle;
        return angle;
    }
    rotateX(degrees) {
        const angle = degToRad(degrees);
        return new CustomVector3(this.x * Math.cos(angle), this.y - Math.sin(angle), this.z * Math.cos(angle));
    }
    rotateY(degrees) {
        const angle = degToRad(degrees);
        return new CustomVector3(this.x * Math.cos(angle) - this.z * Math.sin(angle), this.y, this.x * Math.sin(angle) + this.z * Math.cos(angle));
    }
    rotate(degrees) {
        return this.rotateX(degrees.x).rotateY(degrees.y);
    }
    roundAll() {
        return new CustomVector3(Math.round(this.x), Math.round(this.y), Math.round(this.z));
    }
    floorAll() {
        return new CustomVector3(Math.floor(this.x), Math.floor(this.y), Math.floor(this.z));
    }
    abs() {
        return new CustomVector3(Math.abs(this.x), Math.abs(this.y), Math.abs(this.z));
    }
    equals(other) {
        return this.x === other.x && this.y === other.y && this.z === other.z;
    }
    toString() {
        return `Vec3(${this.x}, ${this.y}, ${this.z})`;
    }
    scale(factor) {
        return new CustomVector3(this.x * factor, this.y * factor, this.z * factor);
    }
    static distance(a, b) {
        return Math.sqrt((a.x - b.x) ** 2 + (a.y - b.y) ** 2 + (a.z - b.z) ** 2);
    }
}
