import 'element-behaviors'
import {numberAttribute} from '@lume/element'
import {TorusGeometry} from 'three/src/geometries/TorusGeometry.js'
import {behavior} from '../../Behavior.js'
import {receiver} from '../../PropReceiver.js'
import {GeometryBehavior} from './GeometryBehavior.js'
import {toRadians} from '../../../core/utils/index.js'

export type TorusGeometryBehaviorAttributes = 'tubeThickness' | 'radialSegments' | 'tubularSegments' | 'arc'

/**
 * @class TorusGeometryBehavior
 *
 * Creates a donut-shaped geometry for [`<lume-mesh>`](../../../meshes/Mesh)
 * elements. This is the geometry behavior of
 * [`<lume-torus>`](../../../meshes/Torus) elements by default.
 *
 * The outer diameter of the donut is determined by the element's
 * [`calculatedSize.x`](../../../core/Sizeable#calculatedsize). The inner diameter is
 * the element's `calculatedSize.x` minus the donut's
 * [`tubeThickness`](#tubethickness).
 *
 * @extends GeometryBehavior
 */
export
@behavior
class TorusGeometryBehavior extends GeometryBehavior {
	// TODO tubeThicknessMode: literal or proportional

	/**
	 * @property {number} tubeThickness -
	 *
	 * `attribute`
	 *
	 * Default: `0.1`
	 *
	 * The thickness of the tube of the donut, as a fraction of the element's
	 * `x` size (as a fraction of the overall diameter also determined by the
	 * element's `x` size). The default `0.1` value means the donut's tube
	 * thickness is 10% of the overall diameter.
	 */
	@numberAttribute @receiver tubeThickness = 0.1

	/**
	 * @property {number} radialSegments -
	 *
	 * `attribute`
	 *
	 * Default: `16`
	 *
	 * The number of segments (or edges) of the circular cross section of the
	 * donut tube.
	 */
	@numberAttribute @receiver radialSegments = 16

	/**
	 * @property {number} tubularSegments -
	 *
	 * `attribute`
	 *
	 * Default: `32`
	 *
	 * The number of tube sections around the donut.
	 */
	@numberAttribute @receiver tubularSegments = 32

	/**
	 * @property {number} arc -
	 *
	 * `attribute`
	 *
	 * Default: `360`
	 *
	 * The total angle in degrees around which the donut is constructed. The
	 * default value of `360` means the tubular segments go all the way around
	 * to form a whole donut. A value of `180` means we get a half of a donut
	 * shape.
	 */
	@numberAttribute @receiver arc = 360

	override _createComponent() {
		const outerDiameter = this.element.calculatedSize.x
		const outerRadius = outerDiameter / 2
		const {tubeThickness, radialSegments, tubularSegments, arc} = this
		const literalThickness = tubeThickness * outerDiameter
		const radius = outerRadius - literalThickness / 2

		return new TorusGeometry(radius, literalThickness, radialSegments, tubularSegments, toRadians(arc))
	}
}

if (globalThis.window?.document && !elementBehaviors.has('torus-geometry'))
	elementBehaviors.define('torus-geometry', TorusGeometryBehavior)
