/**
 * @author oosmoxiecode
 * @author mrdoob / http://mrdoob.com/
 * @author Mugen87 / https://github.com/Mugen87
 */

import { Geometry } from "../Geometry";
import { Vector3 } from "../math/Vector3";

export class TorusGeometry extends Geometry {
	constructor(
		radius = 1,
		tube = 0.4,
		radialSegments = 8,
		tubularSegments = 6,
		arc = Math.PI * 2
	) {

		radialSegments = Math.floor(radialSegments);
		tubularSegments = Math.floor(tubularSegments);

		// buffers
		const indices = [];
		const vertices = [];
		const normals = [];
		const uvs = [];

		// helper variables
		const center = new Vector3();
		const vertex = new Vector3();
		const normal = new Vector3();

		let j, i;

		// generate vertices, normals and uvs
		for (j = 0; j <= radialSegments; j++) {

			for (i = 0; i <= tubularSegments; i++) {

				var u = i / tubularSegments * arc;
				var v = j / radialSegments * Math.PI * 2;

				// vertex
				vertex.x = (radius + tube * Math.cos(v)) * Math.cos(u);
				vertex.y = (radius + tube * Math.cos(v)) * Math.sin(u);
				vertex.z = tube * Math.sin(v);

				vertices.push(vertex.x, vertex.y, vertex.z);

				// normal
				center.x = radius * Math.cos(u);
				center.y = radius * Math.sin(u);
				normal.subVectors(vertex, center).normalize();

				normals.push(normal.x, normal.y, normal.z);

				// uv
				uvs.push(i / tubularSegments);
				uvs.push(1 - j / radialSegments);

			}

		}

		// generate indices
		for (j = 1; j <= radialSegments; j++) {

			for (i = 1; i <= tubularSegments; i++) {

				// indices
				const a = (tubularSegments + 1) * j + i - 1;
				const b = (tubularSegments + 1) * (j - 1) + i - 1;
				const c = (tubularSegments + 1) * (j - 1) + i;
				const d = (tubularSegments + 1) * j + i;

				// faces
				indices.push(a, b, d);
				indices.push(b, c, d);

			}

		}

		super(vertices, indices, normals, null, uvs);
	}
}

