import { Utils, Mesh } from '@uino/thing';
/**
	 * 体积网格。
	 * @class VolumeMesh
	 * @public
	 * @memberof THING
	 * @example
	 * let volumeMesh = new THING.VolumeMesh({
	 * 	data: {
	 * 		position: [x, y, z, x1, y1, y2, .... ],
	 * 		index: [1 ,2, 3, ...]
	 * 	},
	 * 	alphaThreshold: 0.1,
	 * 	opacity: 0.5,
	 * 	unitDistanceOpacity: 0.1,
	 * 	mixType: 'mix',
	 * 	colorRampTexture: new THING.ImageTexture({ url: 'http://xxx.png' }),
	 * 	ValueAffectsOpacity: true,
	 * 	volumeSize: [x, y, z],
	 * 	volumeOffset: [x, y, z],
	 * 	volumeRotation: [x, y, z],
	 * 	particleRadius: 0.7,
	 * 	particleDensity: 1.6,
	 * 	isParticleBased: true
	 * });
	 */
class VolumeMesh extends Mesh {
	
	/**
	 * @constructor
	 * @public
	 * @summary 构造函数
	 * @param {object} param
	 * @param {object} param.data 剪辑形状数据 {position: [x, y, z, x1, y1, y2, .... ], index: [1 ,2, 3, ...]}
	 * @param {number} param.alphaThreshold 默认值 0 范围 0 - 1
	 * @param {number} param.opacity 默认值 0 范围 0 - 1
	 * @param {number} param.unitDistanceOpacity 默认值 1.2 范围 0 - 10
	 * @param {string} param.mixType 混合类型 "mix" 或 "normal" 默认值 "normal"
	 * @param {ImageTexture} param.colorRampTexture 颜色渐变纹理
	 * @param {boolean} param.ValueAffectsOpacity 值是否影响透明度 默认值 true
	 * @param {Array} param.volumeSize 体积大小 [x, y, z]
	 * @param {Array} param.volumeOffset 体积偏移 [x, y, z]
	 * @param {Array} param.volumeRotation 体积旋转 [x, y, z]
	 * @param {number} param.particleRadius 粒子半径 默认值 0.7
	 * @param {number} param.particleDensity 粒子密度 默认值 1.6
	 * @param {boolean} param.isParticleBased 是否粒子化 默认值 true
	 **/
	constructor(param) {
		super(param);
	}

	/**
	 * @private
	**/
	_createCustomNode(param) {
		super._loadGeometryResource(param)
		let geometryResource =  this.geometry;

		return Utils.createObject('VolumeEffectNode', { external: { node: this.node, camera: this.app.camera, view: this.app.view, param: param, geometryResource }});
	}

	/**
	 * @private
	**/
	onLoadResource(options, resolve, reject) {
		let dynamic = Utils.parseValue(options['dynamic'], false);
		if (!dynamic) {
			Utils.setTimeout(() => {
				if (this.destroyed) {
					reject(`The object had been destroyed, skip to load resources`);
				}
				else {
					let node = this._createCustomNode(options);

					this.body.setNode(node);

					resolve();
				}
			});
		}
	}

	/**
	 * 网格不透明度(默认值 1,范围 0 - 1)。
	 * @type {boolean}
	 * @public
	 */
	set opacity(opacity) {
		this.node.setOpacity(opacity);
	}

	get opacity() {
		return	this.node.getOpacity();
	}

	/**
	 * 此对象与场景颜色的混合方法(混合类型为 mix 或 "normal",默认值为 "normal")
	 * @type {string}
	 * @public
	 */
	set mixType(value) {
		this.node.setMixType(value);
	}

	get mixType() {
		return	this.node.getMixType();
	}

	/**
	 * Alpha 阈值,低于此值的项将被裁剪(默认值 0,范围 0 - 1)
	 * @type {number}
	 * @public
	 */
	set alphaThreshold(value) {
		this.node.setAlphaThreshold(value);
	}

	get alphaThreshold() {
		return this.node.getAlphaThreshold();
	}

	/**
	 * 每单位距离内的透明度(默认值 1.2,范围 0 - 10)
	 * @type {number}
	 * @public
	 */
	set unitDistanceOpacity(value) {
		this.node.setUnitDistanceOpacity(value);
	}

	get unitDistanceOpacity() {
		return this.node.getUnitDistanceOpacity();
	}

	/**
	 * 对象渲染数据是否影响透明度(默认值为 true)
	 * @type {boolean}
	 * @public
	 */
	set valueOpacityEnable(value) {
		this.node.setValueAffectsOpacity(value);
	}

	get valueOpacityEnable() {
		return this.node.getValueAffectsOpacity();
	}

	set particleRadius(value) {
		this.node.setParticleRadius(value);
	}

	get particleRadius() {
		return this.node.getParticleRadius();
	}


	set isParticleBased(value) {
		this.node.setIsParticleBased(value);
	}

	get isParticleBased() {
		return this.node.getIsParticleBased();
	}

	set particleDensity(value) {
		this.node.setParticleDensity(value);
	}

	get particleDensity() {
		return this.node.getParticleDensity();
	}

	set maskIntensity(value) {
		this.node.setMaskIntensity(value);
	}

	get maskIntensity() {
		return this.node.getMaskIntensity();
	}

	set lightDirection(value) {
		this.node.setLightDirection(value);
	}

	get lightDirection() {
		return this.node.getLightDirection();
	}
	/**
	 * Set HeatAtPoint
	 * @param {object} object
	 * @param {object} object.data
	 * @param {object} object.data.size data format{ x,  y, z }
	 * @param {Array} object.data.points data format[[x,y,z,value],[x,y,z,value]]
	 * @param {Array} object.data.range data format[x,y,z]The data range starts from the data center [0, 0, 0] and points within the positive and negative range radius,
	 * @param {number} object.data.radius Data radius
	 * @param {object} object.textureSize [Size, Size, Size], if it is a 3D texture, the texture size needs to be set
	 * @example
	 * heatCloudData = {
	 * size: { x: 256, y: 256, z: 256 },
	 * points: [[x, y, z, value], [x, y, z, value]],
	 * range: [x, y, z],
	 * radius: 10
	 * }
	 * volumeMesh.setHeatAtPoint({ data: heatCloudData, textureSize: [SIZE, SIZE, SIZE]});
	 * @private
	 */
	_setHeatAtPoint(object) {
		if (this.node._children.length > 0) {
			this.node._children[0].setHeatAtPoint(object);
		}
		else {
			this.node.setHeatAtPoint(object);
		}
	}

	/**
	 * Set HeatAtPoint
	 * @param {object} object
	 * @param {object} object.data
	 * @param {object} object.data.size data format{ x,  y, z }
	 * @param {Array} object.data.points data format[[x,y,z,value],[x,y,z,value]]
	 * @param {Array} object.data.range data format[x,y,z]The data range starts from the data center [0, 0, 0] and points within the positive and negative range radius,
	 * @param {number} object.data.radius Data radius
	 * @param {number} object.data.type Data type
	 * @param {object} object.textureSize [Size, Size, Size], if it is a 3D texture, the texture size needs to be set
	 * @example
	 * heatCloudData = {
	 * size: { x: 256, y: 256, z: 256 },
	 * points: [[x, y, z, value], [x, y, z, value]],
	 * range: [x, y, z],
	 * radius: 10
	 * type: 'temperature'
	 * }
	 * volumeMesh.setHeatAtPoint({ data: heatCloudData, textureSize: [SIZE, SIZE, SIZE]});
	 * @private
	 */
	_setTemperatureAtPoint(object) {
		if (this.node._children.length > 0) {
			this.node._children[0].setTemperatureAtPoint(object);
		}
		else {
			this.node.setTemperatureAtPoint(object);
		}
	}

	/**
	 * Set Texture
	 * @param {object} object
	 * @param {ImageTexture} object.data 3DTexture ImageTexture
	 * @param {number} object.ZSLICEX,
	 * @param {number} object.ZSLICEY,
	 * @param {number} object.ZSLICENUM,
	 * @param {object} object.textureSize [SIZE, SIZE,SIZE],
	 * @example
	 * let texture = new THING.ImageTexture({ url: 'http://xxx.png' });
	 * volumeMesh.setTexture({ data: texture, ZSLICEX:16, ZSLICEY:16, ZSLICENUM:256});
	 * @private
	 */
	_setTexture(object) {
		this.node.setTexture(object);
	}

	/**
	 * Set ArrayBuffer
	 * @param {object} object
	 * @param {Uint8Array} object.data 3DTexture ArrayBuffer
	 * @param {object} object.textureSize [SIZE, SIZE, SIZE]
	 * @example
	 * let arrayBuffer = new Uint8Array(data);
	 * volumeMesh.setArrayBuffer({ data: arrayBuffer, textureSize: [SIZE, SIZE, SIZE]});
	 * @private
	 */
	_setArrayBuffer(object) {
		this.node.setArrayBuffer(object);
	}

	/**
	 * 设置体积数据
	 * @param {object} object - 体积数据对象
	 * @param {object} object.data - 包含体积数据的详细信息
	 * @param {number} object.data.radius - 体积的半径
	 * @param {string} object.data.type - 体积数据的类型,支持 'temperature' 和其他类型
	 * @public
	 */
	setData(object) {
		if (object.data.radius) {
			if (object.data.type == 'temperature') {
				this._setTemperatureAtPoint(object);
			}
			else {
				this._setHeatAtPoint(object);
			}
		}
		else if (object.data.isImageTexture) {
			this._setTexture(object);
		}
		else {
			this._setArrayBuffer(object);
		}
	}

}

export { VolumeMesh };