import { BinaryClassSerializationAdapter } from "../../../ecs/storage/binary/BinaryClassSerializationAdapter.js";
import { SequenceBehavior } from "../composite/SequenceBehavior.js";
import { SucceedingBehavior } from "../primitive/SucceedingBehavior.js";
import { BehaviorComponent } from "./BehaviorComponent.js";

export class BehaviorComponentSerializationAdapter extends BinaryClassSerializationAdapter {

    klass = BehaviorComponent;
    version = 0;

    /**
     *
     * @type {BinaryObjectSerializationAdapter}
     */
    objectAdapter = null;

    /**
     *
     * @param {BehaviorSystem} system
     * @param {BinaryObjectSerializationAdapter} objectAdapter
     */
    initialize(system, objectAdapter) {
        this.objectAdapter = objectAdapter;
    }

    /**
     *
     * @param {BinaryBuffer} buffer
     * @param {BehaviorComponent} value
     */
    serialize(buffer, value) {
        buffer.writeUint8(value.clock);
        buffer.writeUint8(value.flags);

        if (value.behavior !== null) {
            buffer.writeUintVar(1);

            //write single behavior
            this.objectAdapter.serialize(buffer, value.behavior);
        } else {
            buffer.writeUintVar(0);
        }
    }

    /**
     *
     * @param {BinaryBuffer} buffer
     * @param {BehaviorComponent} value
     */
    deserialize(buffer, value) {
        const clock = buffer.readUint8();
        const flags = buffer.readUint8();

        const n = buffer.readUintVar();

        const behaviors = [];

        for (let i = 0; i < n; i++) {
            /**
             * Read a single behavior
             * @type {Behavior}
             */
            const behavior = this.objectAdapter.deserialize(buffer);

            behaviors.push(behavior);
        }

        //write object fields
        value.clock = clock;
        value.flags = flags;

        if (behaviors.length > 1) {
            value.behavior = SequenceBehavior.from(behaviors);
        } else if (behaviors.length === 1) {
            value.behavior = behaviors[0];
        } else {
            value.behavior = SucceedingBehavior.INSTANCE;
        }
    }
}
