/**
 * this node does not change its input, but displays a piano 🎹 to play the instrument (such as a synthetizer) from the input, if there is one.
 *
 *
 */
import {TypedAudioNode} from './_Base';
import {NodeParamsConfig, ParamConfig} from '../utils/params/ParamsConfig';
import {AudioBuilder} from '../../../core/audio/AudioBuilder';
import {ALL_NOTES, DEFAULT_NOTE} from '../../../core/audio/Notes';

class PlayInstrumentAudioParamsConfig extends NodeParamsConfig {
	/** @param note */
	note = ParamConfig.STRING(DEFAULT_NOTE, {
		menuString: {
			entries: ALL_NOTES.sort().map((note) => {
				return {value: note, name: note};
			}),
		},
		cook: false,
	});
	/** @param duration */
	duration = ParamConfig.FLOAT(0.125, {
		range: [0, 1],
		rangeLocked: [true, false],
		cook: false,
	});
	/** @param play the audio */
	// play = ParamConfig.BUTTON(null, {
	// 	callback: (node: BaseNodeType) => {
	// 		PlayInstrumentAudioNode.PARAM_CALLBACK_play(node as PlayInstrumentAudioNode);
	// 	},
	// });
	/** @param stop the audio */
	// stop = ParamConfig.BUTTON(null, {
	// 	callback: (node: BaseNodeType) => {
	// 		PlayInstrumentAudioNode.PARAM_CALLBACK_stop(node as PlayInstrumentAudioNode);
	// 	},
	// });
	showNotes = ParamConfig.BOOLEAN(0, {separatorBefore: true});
	showKeys = ParamConfig.BOOLEAN(0);
	startOctave = ParamConfig.INTEGER(2, {range: [1, 8], rangeLocked: [false, false]});
	endOctave = ParamConfig.INTEGER(4, {range: [1, 8], rangeLocked: [false, false]});
	updateNoteFromInstrument = ParamConfig.BOOLEAN(0);
}
const ParamsConfig = new PlayInstrumentAudioParamsConfig();

export class PlayInstrumentAudioNode extends TypedAudioNode<PlayInstrumentAudioParamsConfig> {
	override paramsConfig = ParamsConfig;
	static override type() {
		return 'playInstrument';
	}

	override initializeNode() {
		this.io.inputs.setCount(1);
	}

	override cook(inputContents: AudioBuilder[]) {
		const audioBuilder = inputContents[0];
		this.setAudioBuilder(audioBuilder);
	}
	async play(): Promise<void> {
		const instrument = await this._getInstrument();
		if (!instrument) {
			console.log('no instrument');
			return;
		}
		// await AudioController.start();
		instrument.triggerAttackRelease(this.pv.note, this.pv.duration);
	}
	// async stop() {
	// 	const instrument = await this._getInstrument();
	// 	if (!instrument) {
	// 		return;
	// 	}
	// 	// TODO: find out how to properly call triggerRelease, without or without the argument
	// }
	private async _getInstrument() {
		if (this.isDirty()) {
			await this.compute();
		}
		const audioBuilder = this.containerController.container().coreContent();
		if (!audioBuilder) {
			return;
		}
		return audioBuilder.instrument();
	}

	// static PARAM_CALLBACK_play(node: PlayInstrumentAudioNode) {
	// 	node.play();
	// }
	// static PARAM_CALLBACK_stop(node: PlayInstrumentAudioNode) {
	// 	node.stop();
	// }
}
