export class events {

	getDomElements( ) {

		const statusElement		= document.getElementById( "status" );

		const canvas			= document.getElementById( "gfx" );

		const waveHeightSlider	= document.getElementById( "waveHeight" );

		const waveHeightValue	= document.getElementById( "waveHeightValue" );

		const wavelengthSlider	= document.getElementById( "wavelengthSlider" );

		const wavelengthValue	= document.getElementById( "wavelengthValue" );

		const resolutionSlider	= document.getElementById( "resolutionSlider" );

		const resolutionValue	= document.getElementById( "resolutionValue" );

		const tilingSlider		= document.getElementById( "tilingSlider" );

		const tilingValue		= document.getElementById( "tilingValue" );

		const wireframeToggle	= document.getElementById( "wireframeToggle" );

		const pauseToggle		= document.getElementById( "pauseToggle" );

		const shadingModeSelect	= document.getElementById( "shadingMode" );

		const stepButton		= document.getElementById( "stepButton" );

		const dumpHeightButton	= document.getElementById( "dumpHeightButton" );

		return {
			statusElement,
			canvas,
			waveHeightSlider,
			waveHeightValue,
			wavelengthSlider,
			wavelengthValue,
			resolutionSlider,
			resolutionValue,
			tilingSlider,
			tilingValue,
			wireframeToggle,
			pauseToggle,
			shadingModeSelect,
			stepButton,
			dumpHeightButton
		};

	}


	setup( ) {

		const domElements			= this.getDomElements( );

		const waveHeightSlider		= domElements.waveHeightSlider;
		const waveHeightValue		= domElements.waveHeightValue;

		const wavelengthSlider		= domElements.wavelengthSlider;
		const wavelengthValue		= domElements.wavelengthValue;

		const resolutionSlider		= domElements.resolutionSlider;
		const resolutionValue		= domElements.resolutionValue;

		const tilingSlider			= domElements.tilingSlider;
		const tilingValue			= domElements.tilingValue;

		const wireframeToggle		= domElements.wireframeToggle;
		const pauseToggle			= domElements.pauseToggle;
		const shadingModeSelect		= domElements.shadingModeSelect;
		const stepButton			= domElements.stepButton;
		const dumpHeightButton		= domElements.dumpHeightButton;

		const getPrimaryPipeline	= this.getPrimaryPipeline;
		const getPipelines			= this.getPipelines;
		const rebuildScene			= this.rebuildScene;

		const getScene				= this.getScene;
		const getRenderSystem		= this.getRenderSystem;

		if ( this.resizeCanvasToDisplay ) {

			window.addEventListener( "resize", function( ) {

				this.resizeCanvasToDisplay( );

			}.bind( this ) );

		}


		const self = this;


		if ( waveHeightSlider && waveHeightValue ) {

			const primary					= getPrimaryPipeline( );

			waveHeightSlider.value			= primary ? String( primary.heightScale ) : "33";
			waveHeightValue.textContent		= primary ? primary.heightScale.toFixed( 0 ) : "33";

			waveHeightSlider.addEventListener( "input", function( event ) {

				const target	= event.target;

				const value		= parseFloat( target.value );

				if ( isNaN( value ) ) {

					return;

				}

				const pipelines	= getPipelines( );

				for ( const p of pipelines ) {

					p.setHeightScale( value );

				}

				waveHeightValue.textContent	= value.toFixed( 0 );

			} );

		}


		if ( wavelengthSlider && wavelengthValue ) {

			const primary						= getPrimaryPipeline( );

			const initialWavelength				= primary && typeof primary.wavelengthScale === "number"
				? primary.wavelengthScale
				: 1.0;

			wavelengthSlider.value				= String( initialWavelength );
			wavelengthValue.textContent			= initialWavelength.toFixed( 2 );

			wavelengthSlider.addEventListener( "input", function( event ) {

				const target	= event.target;

				const value		= parseFloat( target.value );

				if ( isNaN( value ) || value <= 0 ) {

					return;

				}

				if ( self.setCurrentWavelengthScale ) {

					self.setCurrentWavelengthScale( value );

				}

				const pipelines	= getPipelines( );

				for ( const p of pipelines ) {

					if ( typeof p.setWavelengthScale === "function" ) {

						p.setWavelengthScale( value );

					}

				}

				wavelengthValue.textContent	= value.toFixed( 2 );

			} );

		}


		if ( wireframeToggle ) {

			const primary			= getPrimaryPipeline( );

			wireframeToggle.checked	= primary ? primary.renderMode === "wireframe" : false;

			wireframeToggle.addEventListener( "change", function( event ) {

				const target	= event.target;

				const pipelines	= getPipelines( );

				if ( target.checked ) {

					for ( const p of pipelines ) {

						p.setRenderMode( "wireframe" );

					}

				} else {

					for ( const p of pipelines ) {

						p.setRenderMode( "solid" );

					}

				}

				rebuildScene( );

			} );

		}


		if ( pauseToggle ) {

			pauseToggle.checked	= false;

			pauseToggle.addEventListener( "change", function( event ) {

				const target	= event.target;

				const pipelines	= getPipelines( );

				for ( const p of pipelines ) {

					p.setPaused( target.checked );

				}

			} );

		}


		if ( shadingModeSelect ) {

			shadingModeSelect.value	= "lighting";

			shadingModeSelect.addEventListener( "change", function( event ) {

				const target	= event.target;

				const value		= target.value;

				const pipelines	= getPipelines( );

				for ( const p of pipelines ) {

					p.setShadingMode( value );

				}

			} );

		}


		if ( stepButton ) {

			stepButton.addEventListener( "click", function( ) {

				const pipelines		= getPipelines( );

				for ( const p of pipelines ) {

					p.stepOnce( 1 / 60 );

				}

				const scene			= getScene( );
				const renderSystem	= getRenderSystem( );

				if ( scene && renderSystem ) {

					renderSystem.render( scene );

				}

			} );

		}


		if ( dumpHeightButton ) {

			dumpHeightButton.addEventListener( "click", function( ) {

				const pipeline = getPrimaryPipeline( );

				if ( !pipeline ) {

					return;

				}

				const block		= pipeline.getBlockByName( "ocean" );

				if ( !block ) {

					return;

				}

				const colPass	= block.getPass( "ColFFT" );

				if ( !colPass || !colPass.shader ) {

					return;

				}

				colPass.shader.debugBuffer( "heightField" )
					.then( function( data ) {

						if ( !data || !data.length ) {

							console.log( "heightField debug: empty buffer" );
							return;

						}

						let min		= data[ 0 ];
						let max		= data[ 0 ];
						let sum		= 0;

						for ( let i = 0; i < data.length; i++ ) {

							const v	= data[ i ];

							if ( v < min ) min = v;
							if ( v > max ) max = v;

							sum += v;

						}

						const avg	= sum / data.length;

						console.log( "heightField debug:",
							"size =", data.length,
							"min =", min,
							"max =", max,
							"avg =", avg
						);

					} )
					.catch( function( error ) {

						console.error( "heightField debug failed:", error );

					} );

			} );

		}


		if ( resolutionSlider && resolutionValue ) {

			const applyResolutionFromSlider = function( ) {

				const raw		= parseFloat( resolutionSlider.value );

				if ( isNaN( raw ) ) {

					return;

				}

				let targetSize	= 64;

				if ( raw < 48 ) {

					targetSize	= 32;

				} else if ( raw < 96 ) {

					targetSize	= 64;

				} else if ( raw < 192 ) {

					targetSize	= 128;

				} else if ( raw < 384 ) {

					targetSize	= 256;

				} else if ( raw < 768 ) {

					targetSize	= 512;

				} else if ( raw < 1536 ) {

					targetSize	= 1024;

				} else {

					targetSize	= 2048;

				}

				resolutionSlider.value		= String( targetSize );
				resolutionValue.textContent	= String( targetSize );

				if ( self.setCurrentMeshResolution ) {

					self.setCurrentMeshResolution( targetSize );

				}

				rebuildScene( );

			};

			applyResolutionFromSlider( );

			resolutionSlider.addEventListener( "input", function( ) {

				applyResolutionFromSlider( );

			} );

		}


		if ( tilingSlider && tilingValue ) {

			const applyTilingFromSlider = function( ) {

				const raw	= parseInt( tilingSlider.value, 10 );

				if ( isNaN( raw ) || raw < 1 ) {

					return;

				}

				const tileRange	= raw - 1;

				tilingValue.textContent	= String( raw );

				if ( self.setCurrentTiling ) {

					self.setCurrentTiling( raw );

				}

				rebuildScene( );

			};

			applyTilingFromSlider( );

			tilingSlider.addEventListener( "input", function( ) {

				applyTilingFromSlider( );

			} );

		}


		if ( domElements.canvas && this.setAutoRotate ) {

			domElements.canvas.addEventListener( "pointerdown", function( ) {

				this.setAutoRotate( false );

			}.bind( this ) );

		}

	}

}
