import { assert } from "../../../core/assert.js";
import { AnimationTrackBinding } from "./AnimationTrackBinding.js";

export class AnimationClipBinding {

    /**
     * @type {AnimationClip}
     */
    clip


    /**
     * Populated by {@link bind} method
     * @type {AnimationTrackBinding[]}
     */
    tracks = []

    /**
     * @deprecated use `clip.name` directly instead
     * @return {string}
     */
    get name() {
        return this.clip.name
    }

    /**
     * @deprecated use `clip.duration` directly instead
     * @return {number}
     */
    get duration() {
        return this.clip.duration;
    }

    static from(clip, root, binding_registry) {
        const r = new AnimationClipBinding();

        r.clip = clip;

        r.bind(root, binding_registry);

        return r;
    }

    /**
     * @template T
     * @param {T} root
     * @param {Object<Type<BoundValueWriter>>} binding_registry
     */
    bind(root, binding_registry) {
        const bound_tracks = this.tracks;

        if (bound_tracks.length > 0) {
            // clear out existing
            bound_tracks.splice(0, bound_tracks.length);
        }

        const clip = this.clip;

        const tracks = clip.tracks;
        const track_count = tracks.length;
        for (let i = 0; i < track_count; i++) {
            const track = tracks[i];

            const WriterClass = binding_registry[track.type];

            if (WriterClass === undefined) {
                throw new Error(`No binding class in registry for track type '${track.type}'`);
            }

            assert.isFunction(WriterClass, 'WriterClass');

            const writer = new WriterClass();

            writer.bind(root, track.path);

            bound_tracks[i] = AnimationTrackBinding.from(writer, track);
        }
    }

    /**
     *
     * @param {number} time time in seconds
     */
    writeAt(time) {
        const tracks = this.tracks;
        const track_count = tracks.length;

        for (let i = 0; i < track_count; i++) {
            const track = tracks[i];

            track.writeAt(time);
        }
    }
}