import { Assets, ExtensionType, LoaderParserPriority } from 'pixi.js';

import type { SoundSpriteDefinition } from '@pixi/sound';

interface AudioSpriteAsset
{
    resources?: string[];
    spritemap?: Record<string, SoundSpriteDefinition>;
}

interface AudioSpriteSheet
{
    addSprites(sprites: Record<string, SoundSpriteDefinition>): void;
}

const AUDIO_EXTENSIONS = ['ogg', 'm4a', 'mp3', 'ac3'] as const;

const stripSoundPrefix = (resource: string): string => resource.replace(/^.*?(?=sounds)/, '');

/** Loader that registers PixiJS audio sprite bundles. */
export const AudioSpriteLoader = {
    extension: ExtensionType.Asset,
    loader: {
        name: 'AudioSpriteLoader',
        extension: {
            type: ExtensionType.LoadParser,
            priority: LoaderParserPriority.Normal,
        },

        async testParse(asset: AudioSpriteAsset): Promise<boolean>
        {
            return !!asset.resources?.some((resource) =>
                AUDIO_EXTENSIONS.some((ext) => resource.toLowerCase().endsWith(ext)));
        },

        async parse(asset: AudioSpriteAsset): Promise<void>
        {
            const resources = asset.resources ?? [];
            const spritemap = asset.spritemap;

            if (resources.length === 0 || !spritemap)
            {
                return;
            }

            const basePath = Assets.resolver.basePath;
            const delimiter = basePath.endsWith('/') ? '' : '/';
            const src = resources.map((resource) => `${basePath}${delimiter}${stripSoundPrefix(resource)}`);
            const [firstSource] = src;

            if (!firstSource)
            {
                return;
            }

            const alias = `${firstSource.replace(/^.*\/(.*?)\..*$/, '$1')}Sheet`;

            Assets.add({ alias, src });

            const soundSheet = await Assets.load<AudioSpriteSheet>(alias);

            soundSheet.addSprites(spritemap);
        },
    },
} as const;
