export const VIEWS = [
	'dashboard',
	'links',
	'history',
	'schedule',
	'settings',
] as const;

export type View = ( typeof VIEWS )[ number ];

export type RouteParams = Readonly< Partial< Record< string, string > > >;

export type Route = {
	view: View;
	params: RouteParams;
};

const HASH_PREFIX = /^#\/?/;
const QUERY_MARK = '?';
const DEFAULT_VIEW: View = 'dashboard';

function isView( name: string ): name is View {
	return ( VIEWS as readonly string[] ).includes( name );
}

function readParams( queryText: string ): RouteParams {
	const params: Record< string, string > = {};

	for ( const [ name, paramValue ] of new URLSearchParams( queryText ) ) {
		if ( paramValue !== '' ) {
			params[ name ] = paramValue;
		}
	}

	return params;
}

export function parseRoute( hash: string ): Route {
	const routeText = hash.replace( HASH_PREFIX, '' );
	const markPosition = routeText.indexOf( QUERY_MARK );
	const hasQuery = markPosition !== -1;
	const viewName = hasQuery ? routeText.slice( 0, markPosition ) : routeText;
	const queryText = hasQuery ? routeText.slice( markPosition + 1 ) : '';

	return {
		view: isView( viewName ) ? viewName : DEFAULT_VIEW,
		params: readParams( queryText ),
	};
}

export function formatRoute( view: View, params: RouteParams ): string {
	const query = new URLSearchParams();

	for ( const name of Object.keys( params ).sort() ) {
		const paramValue = params[ name ];

		if ( paramValue !== undefined && paramValue !== '' ) {
			query.set( name, paramValue );
		}
	}

	const queryText = query.toString();
	const path = view === DEFAULT_VIEW ? '' : view;
	const querySuffix = queryText === '' ? '' : `?${ queryText }`;

	return `#/${ path }${ querySuffix }`;
}
