import { SourceType } from './source-type';
export class StreamingSource {
    constructor(graph, scene, context, element, type = SourceType.MasterSource) {
        this.graph = graph;
        this.scene = scene;
        this.context = context;
        this.element = element;
        this.type = type;
        this.filterFreq = 24000;
        this.position = {
            x: 0,
            y: 0,
            z: 0
        };
        this.init();
    }
    init() {
        this.node = this.context.createMediaElementSource(this.element);
        this.filter = this.context.getContext().createBiquadFilter();
        this.filter.type = "lowshelf";
        this.filter.gain.value = -60;
        this.filter.frequency.value = this.filterFreq;
        this.gain = this.context.createGain();
        this.createConnections();
        this.element.addEventListener('canplay', (event) => {
            this.canPlay = true;
            if (this.playOnAvailable) {
                this.play();
            }
        });
    }
    play(when = 0, offset = 0, duration = 0) {
        if (this.canPlay) {
            this.element.play();
        }
        this.playOnAvailable = true;
    }
    stop() {
        this.element.pause();
    }
    getVolume() {
        return this.element.volume;
    }
    setVolume(value) {
        this.element.volume = value;
    }
    getPlaybackRate() {
        return this.element.playbackRate;
    }
    setPlaybackRate(value) {
        this.element.playbackRate = value;
    }
    createConnections() {
        switch (this.type) {
            case SourceType.WorldSource:
                if (!this.sceneNode) {
                    this.sceneNode = this.scene.createSource();
                    this.updateSpatialization();
                }
                this.node.connect(this.filter);
                this.filter.connect(this.gain);
                this.gain.connect(this.sceneNode);
                break;
            default:
                this.node.connect(this.gain);
                this.graph.connectToMaster(this.gain);
                break;
        }
    }
    setPosition(x, y, z) {
        this.position = {
            x,
            y,
            z
        };
        if (this.sceneNode)
            this.sceneNode.setPosition(x, y, z);
    }
    destroy() {
        this.stop();
        this.element = null;
        this.graph = null;
        this.context = null;
        this.node = null;
        this.sceneNode = null;
        this.scene = null;
    }
    loop(value) {
        this.element.loop = true;
    }
    fadeIn(time) {
        this.gain.gain.setValueAtTime(0.0001, this.context.getContext().currentTime);
        if (!this.node) {
            this.play();
        }
        this.gain.gain.exponentialRampToValueAtTime(this.getVolume(), this.context.getContext().currentTime + time);
    }
    fadeOut(time) {
        this.gain.gain.setValueAtTime(this.getVolume(), this.context.getContext().currentTime);
        if (!this.node) {
            return;
        }
        this.gain.gain.exponentialRampToValueAtTime(0.0001, this.context.getContext().currentTime + time);
        setTimeout(() => this.stop(), time * 1000);
    }
    isPlaying() {
        return this.playing;
    }
    setDistanceModel(distanceModel) {
        this.distanceModel = distanceModel;
        this.updateSpatialization();
    }
    setMaxDistance(distance) {
        this.maxDistance = this.maxDistance;
        this.updateSpatialization();
    }
    setRefDistance(ref) {
        this.refDistance = ref;
        this.updateSpatialization();
    }
    setRollOffFactor(factor) {
        this.rollOffFactor = factor;
        this.updateSpatialization();
    }
    updateSpatialization() {
        if (this.sceneNode) {
            this.sceneNode.distanceModel = this.distanceModel;
            this.sceneNode.refDistance = this.refDistance;
            this.sceneNode.rolloffFactor = this.rollOffFactor;
            this.sceneNode.maxDistance = this.maxDistance;
        }
    }
    setFilterFrequency(value) {
        this.filterFreq = value;
        if (this.filter) {
            this.filter.frequency.value = this.filterFreq;
        }
    }
}
