import { combine_hash } from "../../../../../core/collection/array/combine_hash.js";
import { computeHashArray } from "../../../../../core/collection/array/computeHashArray.js";
import { isArrayEqual } from "../../../../../core/collection/array/isArrayEqual.js";
import { invokeObjectHash } from "../../../../../core/model/object/invokeObjectHash.js";
import { computeStringHash } from "../../../../../core/primitives/strings/computeStringHash.js";

/**
 *
 * @param {AnimationNotification} a
 * @param {AnimationNotification} b
 * @returns {number}
 */
function compareByTime(a, b) {
    return a.time - b.time;
}

export class AnimationClipDefinition {
    constructor() {
        /**
         *
         * @type {string}
         */
        this.name = "";

        /**
         * Generic string tags
         * @type {string[]}
         */
        this.tags = [];

        /**
         *
         * @type {number}
         */
        this.duration = 0;

        /**
         * Notifications sorted by time, earliest first
         * @type {AnimationNotification[]}
         */
        this.notifications = [];
    }

    sortNotification() {
        this.notifications.sort(compareByTime);
    }

    /**
     *
     * @param {string} name
     * @return {number}
     */
    countNotificationsByName(name) {
        let result = 0;

        const notifications = this.notifications;
        const n = notifications.length;
        for (let i = 0; i < n; i++) {
            const notification = notifications[i];

            if (notification.def.event === name) {
                result++;
            }

        }

        return result;
    }

    /**
     *
     * @param {string} tag
     * @return {boolean}
     */
    hasTag(tag) {
        const tags = this.tags;

        const n = tags.length;

        for (let i = 0; i < n; i++) {
            const t = tags[i];

            if (t === tag) {
                return true;
            }
        }

        return false;
    }

    /**
     *
     * @param {AnimationClipDefinition} other
     * @returns {boolean}
     */
    equals(other) {
        if (this === other) {
            return true;
        }

        return this.name === other.name
            && isArrayEqual(this.notifications, other.notifications)
            && isArrayEqual(this.tags, other.tags)
            ;
    }

    /**
     * @returns {number}
     */
    hash() {
        return combine_hash(
            computeStringHash(this.name),
            computeHashArray(this.notifications, invokeObjectHash),
            computeHashArray(this.tags, computeStringHash)
        );
    }
}
