import { assert } from "../../../core/assert.js";
import DataType from "../../../core/parser/simple/DataType.js";

export class AbstractBlackboard {

    /**
     * Checks is the blackboard contains a certain value or not by name/type combination
     * @param {string} name
     * @param {DataType} type
     * @returns {boolean}
     */
    contains(name, type) {
        throw new Error('Not implemented');
    }

    /**
     * Produces a list of all held keys
     * @returns {string[]}
     */
    getKeys() {
        throw new Error('Not implemented');
    }

    /**
     * @template T
     * @param {string} name
     * @param {DataType} type
     * @param {string|number|boolean} [initialValue]
     * @returns {T}
     */
    acquire(name, type, initialValue) {
        throw new Error('Not implemented');
    }

    /**
     * Release reference to a value
     * @param {string} name
     * @returns {void}
     */
    release(name) {
        throw new Error('Not implemented');
    }

    /**
     *
     * @param {string} name
     * @param {boolean} [initialValue=false]
     * @returns {ObservedBoolean}
     */
    acquireBoolean(name, initialValue = false) {
        assert.isBoolean(initialValue, 'initialValue');

        return this.acquire(name, DataType.Boolean, initialValue);
    }

    /**
     *
     * @param {string} name
     * @param {number} [initialValue=0]
     * @returns {Vector1}
     */
    acquireNumber(name, initialValue = 0) {
        assert.isNumber(initialValue, 'initialValue');

        return this.acquire(name, DataType.Number, initialValue);
    }

    /**
     *
     * @param {string} name
     * @param {number} [value=1]
     * @returns {void}
     */
    incrementNumber(name, value = 1) {
        const vector1 = this.acquireNumber(name);

        vector1._add(value);

        this.release(name);
    }

    /**
     *
     * @param {string} name
     * @param {string} [initialValue]
     * @returns {ObservedString}
     */
    acquireString(name, initialValue = '') {
        assert.isString(initialValue, 'initialValue');

        return this.acquire(name, DataType.String, initialValue);
    }
}
