import { BinaryClassSerializationAdapter } from "../../ecs/storage/binary/BinaryClassSerializationAdapter.js";
import DataType from "../../../core/parser/simple/DataType.js";
import { Blackboard } from "./Blackboard.js";
import { BlackboardValue } from "./BlackboardValue.js";

export class BlackboardSerializationAdapter extends BinaryClassSerializationAdapter {

    klass = Blackboard;
    version = 0;

    /**
     *
     * @param {BinaryBuffer} buffer
     * @param {Blackboard} value
     */
    serialize(buffer, value) {

        const keys = Object.keys(value.data);

        const numKeys = keys.length;

        buffer.writeUint32(numKeys);
        for (let i = 0; i < numKeys; i++) {
            const key = keys[i];

            // write key
            buffer.writeUTF8String(key);

            const datum = value.data[key];

            //write type
            switch (datum.type) {
                case DataType.Number:
                    buffer.writeUint8(1);
                    break;
                case DataType.Boolean:
                    buffer.writeUint8(2);
                    break;
                case DataType.String:
                    buffer.writeUint8(3);
                    break;
                default:
                    throw new TypeError(`Unexpected data type '${datum.type}'`);
            }

            //write value
            datum.value.toBinaryBuffer(buffer);
        }
    }

    /**
     *
     * @param {BinaryBuffer} buffer
     * @param {Blackboard} value
     */
    deserialize(buffer, value) {
        const data = {};

        const numKeys = buffer.readUint32();

        for (let i = 0; i < numKeys; i++) {
            const key = buffer.readUTF8String();

            const typeFlag = buffer.readUint8();

            let type;
            switch (typeFlag) {
                case 1:
                    type = DataType.Number;
                    break;
                case 2:
                    type = DataType.Boolean;
                    break;
                case 3:
                    type = DataType.String;
                    break;
                default:
                    throw new TypeError(`Unexpected data type flag '${typeFlag}'`);
            }

            const blackboardValue = new BlackboardValue(type);

            //read data value
            blackboardValue.value.fromBinaryBuffer(buffer);

            data[key] = blackboardValue;
        }

        value.data = data;
    }
}
