/**
 * Creates a Mesh Phong Material, which can be extended with GL nodes.
 *
 * @remarks
 * This node can create children, which will be GL nodes. The GLSL code generated by the nodes will extend the Material.
 *
 */
import {NodeParamsConfig} from '../utils/params/ParamsConfig';
import {
	UniformsTransparencyParamConfig,
	UniformsTransparencyController,
	UniformsTransparencyControllers,
} from './utils/UniformsTransparencyController';
import {
	AdvancedCommonController,
	AdvancedCommonControllers,
	AdvancedCommonParamConfig,
} from './utils/AdvancedCommonController';
import {MapParamConfig, TextureMapController, TextureMapControllers} from './utils/TextureMapController';
import {
	AlphaMapParamConfig,
	TextureAlphaMapController,
	TextureAlphaMapControllers,
} from './utils/TextureAlphaMapController';
import {BaseBuilderParamConfig, TypedBuilderMatNode} from './_BaseBuilder';
import {ShaderAssemblerPhong} from '../gl/code/assemblers/materials/Phong';
import {AssemblerName} from '../../poly/registers/assemblers/_BaseRegister';
import {Poly} from '../../Poly';
import {FogParamConfig, UniformFogController, UniformFogControllers} from './utils/UniformsFogController';
import {
	WireframeShaderMaterialController,
	WireframeShaderMaterialControllers,
	WireframeShaderMaterialParamsConfig,
} from './utils/WireframeShaderMaterialController';
import {TextureAOMapController, AOMapParamConfig, TextureAOMapControllers} from './utils/TextureAOMapController';
import {
	TextureEnvMapSimpleController,
	EnvMapSimpleParamConfig,
	TextureEnvMapSimpleControllers,
} from './utils/TextureEnvMapSimpleController';
import {
	TextureLightMapController,
	LightMapParamConfig,
	TextureLightMapControllers,
} from './utils/TextureLightMapController';
import {
	TextureEmissiveMapController,
	EmissiveMapParamConfig,
	TextureEmissiveMapControllers,
} from './utils/TextureEmissiveMapController';

import {DefaultFolderParamConfig} from './utils/DefaultFolder';
import {TexturesFolderParamConfig} from './utils/TexturesFolder';
import {AdvancedFolderParamConfig} from './utils/AdvancedFolder';
import {
	TextureBumpMapController,
	BumpMapParamConfig,
	TextureBumpMapControllers,
} from './utils/TextureBumpMapController';
import {
	TextureDisplacementMapController,
	DisplacementMapParamConfig,
	TextureDisplacementMapControllers,
} from './utils/TextureDisplacementMapController';
import {
	TextureNormalMapController,
	NormalMapParamConfig,
	TextureNormalMapControllers,
} from './utils/TextureNormalMapController';
import {
	TextureSpecularMapController,
	SpecularMapParamConfig,
	TextureSpecularMapControllers,
} from './utils/TextureSpecularMapController';
import {PCSSController, PCSSControllers, PCSSParamConfig} from './utils/PCSSController';
import {CustomMaterialName, IUniforms} from '../../../core/geometry/Material';
import {Material, MeshPhongMaterial} from 'three';
import {MatType} from '../../poly/registers/nodes/types/Mat';
import {
	CustomMaterialMeshParamConfig,
	materialMeshAssemblerCustomMaterialRequested,
} from './utils/customMaterials/CustomMaterialMesh';
interface MeshPhongBuilderMaterial extends MeshPhongMaterial {
	vertexShader: string;
	fragmentShader: string;
	uniforms: IUniforms;
	customMaterials: {
		[key in CustomMaterialName]?: Material;
	};
}
interface MeshPhongBuilderControllers
	extends AdvancedCommonControllers,
		PCSSControllers,
		TextureAlphaMapControllers,
		TextureAOMapControllers,
		TextureBumpMapControllers,
		TextureDisplacementMapControllers,
		TextureEmissiveMapControllers,
		TextureEnvMapSimpleControllers,
		TextureLightMapControllers,
		TextureMapControllers,
		TextureNormalMapControllers,
		TextureSpecularMapControllers,
		UniformFogControllers,
		UniformsTransparencyControllers,
		WireframeShaderMaterialControllers {}
class MeshPhongBuilderMatParamsConfig extends CustomMaterialMeshParamConfig(
	PCSSParamConfig(
		FogParamConfig(
			WireframeShaderMaterialParamsConfig(
				AdvancedCommonParamConfig(
					BaseBuilderParamConfig(
						/* advanced */
						AdvancedFolderParamConfig(
							SpecularMapParamConfig(
								NormalMapParamConfig(
									LightMapParamConfig(
										EnvMapSimpleParamConfig(
											EmissiveMapParamConfig(
												DisplacementMapParamConfig(
													BumpMapParamConfig(
														AOMapParamConfig(
															AlphaMapParamConfig(
																MapParamConfig(
																	/* textures */
																	TexturesFolderParamConfig(
																		UniformsTransparencyParamConfig(
																			DefaultFolderParamConfig(NodeParamsConfig)
																		)
																	)
																)
															)
														)
													)
												)
											)
										)
									)
								)
							)
						)
					)
				)
			)
		)
	)
) {}
const ParamsConfig = new MeshPhongBuilderMatParamsConfig();

export class MeshPhongBuilderMatNode extends TypedBuilderMatNode<
	MeshPhongBuilderMaterial,
	ShaderAssemblerPhong,
	MeshPhongBuilderMatParamsConfig
> {
	override paramsConfig = ParamsConfig;
	static override type() {
		return MatType.MESH_PHONG_BUILDER;
	}
	public override usedAssembler(): Readonly<AssemblerName.GL_MESH_PHONG> {
		return AssemblerName.GL_MESH_PHONG;
	}
	protected _createAssemblerController() {
		return Poly.assemblersRegister.assembler(this, this.usedAssembler());
	}
	public override customMaterialRequested(customName: CustomMaterialName): boolean {
		return materialMeshAssemblerCustomMaterialRequested(this, customName);
	}
	readonly controllers: MeshPhongBuilderControllers = {
		advancedCommon: new AdvancedCommonController(this),
		alphaMap: new TextureAlphaMapController(this),
		aoMap: new TextureAOMapController(this),
		bumpMap: new TextureBumpMapController(this),
		displacementMap: new TextureDisplacementMapController(this),
		emissiveMap: new TextureEmissiveMapController(this),
		envMap: new TextureEnvMapSimpleController(this),
		lightMap: new TextureLightMapController(this),
		map: new TextureMapController(this),
		normalMap: new TextureNormalMapController(this),
		specularMap: new TextureSpecularMapController(this),
		PCSS: new PCSSController(this),
		uniformFog: new UniformFogController(this),
		uniformTransparency: new UniformsTransparencyController(this),
		wireframeShader: new WireframeShaderMaterialController(this),
	};
	protected override controllersList = Object.values(this.controllers);

	override async cook() {
		this._material = this._material || this.createMaterial();
		await Promise.all(this.controllersPromises(this._material));

		this.compileIfRequired(this._material);

		this.setMaterial(this._material);
	}
}
