(() => {
	'use strict';

	/**
	 * @property {array} packages
	 * @property {string} cleanup
	 */

	if ( ( typeof packages === 'undefined' ) || ( typeof cleanup === 'undefined' ) ) {
		return;
	}

	let packagesMessage = null;
	let packagesErrored = 0;

	async function uninstallInstaller() {
		const install = await fetch( cleanup, {
			method: 'GET',
			cache: 'no-cache'
		});

		if ( ! install.ok ) {
			if ( packagesErrored ) {
				document.querySelector( '.cbPkgInstaller .progress-bar' ).classList.add( 'bg-danger' );
			} else {
				document.querySelector( '.cbPkgInstaller .progress-bar' ).classList.add( 'bg-warning' );
			}

			document.querySelector( '.cbPkgInstallProgress' ).classList.remove( 'hidden' );

			packageInstallProgress( ( packages.length + 1 ) );
		} else {
			if ( packagesMessage && ( ! packagesErrored ) ) {
				document.querySelector( '.cbPkgInstall' ).innerHTML = '<strong>' + packagesMessage + '</strong>';
			} else {
				if ( packagesErrored ) {
					document.querySelector( '.cbPkgInstaller .progress-bar' ).classList.add( 'bg-danger' );
				} else {
					document.querySelector( '.cbPkgInstaller .progress-bar' ).classList.add( 'bg-success' );
				}

				packageInstallProgress( ( packages.length + 1 ) );
			}
		}

		const refresh = document.querySelector( '.cbWebRefresh' );

		if ( refresh ) {
			refresh.click();
		}
	}

	function packageInstallSuccess( step, msg ) {
		document.querySelector( '.cbPkgInstallRow' + step ).classList.add( 'cbPkgInstallRowInstalled' );
		document.querySelector( '.cbPkgInstallRow' + step + ' .cbPkgInstallState' ).classList.add( 'hidden' );
		document.querySelector( '.cbPkgInstallRow' + step + ' .cbPkgInstallStateInstalled' ).classList.remove( 'hidden' );

		const card = document.querySelector( '.cbPkgInstallRow' + step + '  .card' );

		card.classList.remove( 'border-info' );
		card.classList.add( 'border-success' );

		packageInstallLog( step, 'success', msg );
		packageInstallProgress( step );
	}

	function packageInstallFailed( step, msg ) {
		packagesErrored++;

		document.querySelector( '.cbPkgInstallRow' + step ).classList.add( 'cbPkgInstallRowFailed' );
		document.querySelector( '.cbPkgInstallRow' + step + ' .cbPkgInstallState' ).classList.add( 'hidden' );
		document.querySelector( '.cbPkgInstallRow' + step + ' .cbPkgInstallStateFailed' ).classList.remove( 'hidden' );

		const card = document.querySelector( '.cbPkgInstallRow' + step + '  .card' );

		card.classList.remove( 'border-info' );
		card.classList.add( 'border-danger' );

		packageInstallLog( step, 'danger', msg );
		packageInstallProgress( step );
	}

	function packageInstallLog( step, type, msg ) {
		if ( ! msg ) {
			return;
		}

		let alert = '';

		if ( Array.isArray( msg ) ) {
			let msgs = '';

			for ( const msgObj of msg ) {
				if ( msgObj.type === 'notice' ) {
					msgObj.type = 'info';
				} else if ( msgObj.type === 'message' ) {
					msgObj.type = 'sccess';
				}

				alert += '<div class="alert alert-' + msgObj.type + '" style="white-space: pre-wrap;">' + msgObj.message + '</div>';
				msgs += ( msgs !== '' ? '\n' : '' ) + msgObj.message;
			}

			msg = msgs;
		} else {
			alert = '<div class="alert alert-' + type + '" style="white-space: pre-wrap;">' + msg + '</div>';
		}

		if ( ( packages.length === 1 ) && ( type === 'success' ) ) {
			packagesMessage = msg;
		}

		const log = document.querySelector( '.cbPkgInstallRow' + step + ' .cbPkgInstallLog' );

		log.innerHTML = alert;
		log.classList.remove( 'hidden' );

		const copy = document.querySelector( '.cbPkgInstallRow' + step+ ' .cbPkgInstallDetailCopyText' );

		copy.value = copy.value + '\n[code]\n' + msg + '\n[/code]';
	}

	function packageInstallProgress( step ) {
		let completeness = ( ( 100 / ( packages.length + 1 ) ) * step );

		if ( completeness > 100 ) {
			completeness = 100;
		}

		const progress = document.querySelector( '.cbPkgInstaller .progress-bar' );

		if ( completeness === 100 ) {
			progress.classList.remove( 'progress-bar-striped', 'progress-bar-animated' );
		}

		progress.setAttribute( 'aria-valuenow', completeness.toString() );
		progress.style.width = completeness.toString() + '%';

		document.querySelector( '.cbPkgInstaller .progress-bar .sr-only' ).innerHTML = completeness.toString() + '% Complete';
	}

	async function installPackages( packages ) {
		for ( const pkg of packages ) {
			document.querySelector( '.cbPkgInstallRow' + pkg.step ).classList.remove( 'hidden' )

			const install = await fetch( pkg.url, {
				method: 'GET',
				cache: 'no-cache'
			});

			const result = await install.text();

			if ( ! install.ok ) {
				packageInstallFailed( pkg.step, result );
			} else {
				packageInstallSuccess( pkg.step, result );
			}
		}
	}

	document.addEventListener( 'DOMContentLoaded', () => {
		document.querySelectorAll( '#system-message-container > joomla-alert[type="success"],#system-message-container > .alert.alert-success' ).forEach( el => el.remove() );

		const container = document.querySelector( '#installer-install > form > .alert' );

		if ( container ) {
			container.classList.remove( 'alert', 'alert-info' );
		}

		document.querySelectorAll( '.cbPkgInstallRow' ).forEach( el => {
			el.addEventListener( 'click', event => {
				if ( ( event.target.tagName.toLowerCase() === 'a' ) || ( event.target.tagName.toLowerCase() === 'button' ) ) {
					return;
				}

				if ( el.classList.contains( 'open' ) ) {
					el.classList.remove( 'open' );
				} else {
					el.classList.add( 'open' );
					el.querySelector( '.cbPkgInstallDetailCopyNote' ).classList.add( 'hidden' );
				}

				el.scrollIntoView({ block: 'center', inline: 'nearest' });
			});
		});

		document.querySelectorAll( '.cbPkgInstallDetailCopyBtn' ).forEach( el => {
			el.addEventListener( 'click', () => {
				document.querySelectorAll( '.cbPkgInstallDetailCopyNote' ).forEach( note => note.classList.add( 'hidden' ) );

				el.parentElement.querySelector( '.cbPkgInstallDetailCopyText' ).select();

				document.execCommand( 'copy' );

				el.parentElement.querySelector( '.cbPkgInstallDetailCopyNote' ).classList.remove( 'hidden' );
			});
		});

		installPackages( packages ).then( () => uninstallInstaller() );
	});
})();