import * as pc from "playcanvas";
import { Debugger, ViverseApp } from './toolkit/core.mjs';
import { SoundControls, VideoTextureControls, } from './toolkit/extension.mjs';
/** @enum {string} */
const SourceType = {
    SoundComponent: 'soundComponent',
    VideoTexture: 'videoTexture',
};
/** @enum {string} */
const RenderSideType = {
    Front: 'front',
    Back: 'back',
    Double: 'double',
};
export class ViverseMediaControls extends pc.Script {
    static scriptName = 'viverseMediaControls';
    controls = null;
    /**
     * The source type for the media controls.
     * SoundComponent – media from a sound component, ensure the ‘sound’ component is added;
     * VideoTexture – media from a video texture, ensure the ‘viverse-video-texture’ script is added.
     * @attribute
     * @title Source
     * @type {SourceType}
     */
    source = SourceType.VideoTexture;
    /**
     * The slot name for the sound component controls.
     * Supports only one slot control. If not provided, one of the slot will be used.
     * Please ensure the slot name exists in the sound component.
     * @attribute
     * @title Slot Name
     * @type {string}
     * @visibleif {source === 'soundComponent'}
     */
    slotName;
    /**
     * The render side for the cover texture.
     * @attribute
     * @title Cover Render Side
     * @type {RenderSideType}
     * @visibleif {source === 'soundComponent'}
     */
    coverRenderSide = RenderSideType.Double;
    /**
     * Cover texture for the sound controls.
     * Please provide square texture for better visual effect. If not provided, default cover will be used.
     * @attribute
     * @title Cover Texture
     * @type {pc.Asset}
     * @resource texture
     * @visibleif {source === 'soundComponent'}
     */
    coverTexture;
    initialize() {
        const viverseApp = ViverseApp.getApplication();
        if (!viverseApp) {
            Debugger.error('[ViverseMediaControls] ViverseApp is not initialized.');
            return;
        }
        if (this.source === SourceType.SoundComponent) {
            this._createSoundControls(viverseApp);
        }
        else if (this.source === SourceType.VideoTexture) {
            this._createVideoTextureControls(viverseApp);
        }
        else {
            Debugger.error(`[ViverseMediaControls] Unsupported source type: ${this.source}`);
        }
        this.on('destroy', this.destroy, this);
    }
    _loadCoverTexture(asset) {
        return new Promise((resolve, reject) => {
            if (asset.type !== 'texture' || asset.loaded)
                return resolve();
            asset.once('load', () => resolve());
            asset.once('error', () => reject());
            if (!this.app.assets.get(asset.id))
                this.app.assets.add(asset);
            this.app.assets.load(asset);
        });
    }
    async _createSoundControls(viverseApp) {
        const sound = this.entity.sound;
        if (!sound) {
            Debugger.error(`[ViverseMediaControls] Sound component is not found on the entity ${this.entity.name}.`);
            return;
        }
        const pcApp = viverseApp.pcApp;
        if (this.coverTexture)
            await this._loadCoverTexture(this.coverTexture);
        const texture = this.coverTexture?.resource;
        this.controls = new SoundControls(pcApp, sound, {
            coverRenderSide: this.coverRenderSide,
            ...(texture && texture instanceof pc.Texture && { coverTexture: texture }),
            ...(this.slotName && { slotName: this.slotName }),
        }, viverseApp);
    }
    _createVideoTextureControls(viverseApp) {
        const script = this.entity.script?.get('viverseVideoTexture');
        if (!script) {
            Debugger.error(`[ViverseMediaControls] viverse-video-texture is not found on the entity ${this.entity.name}.`);
            return;
        }
        const create = (videoTexture) => {
            this.controls = new VideoTextureControls(this.app, videoTexture, viverseApp);
        };
        if (script.videoTexture) {
            create(script.videoTexture);
        }
        else {
            script.once('texture:ready', create);
        }
        script.once('destroy', this.destroy, this);
    }
    destroy() {
        this.controls?.destroy();
        this.controls = null;
    }
}
