import { isArrayEqual } from "../../../collection/array/isArrayEqual.js";
import { DataType } from "./DataType.js";
import { deserializeDataTypeFromJSON } from "./deserializeDataTypeFromJSON.js";

/**
 * Loosely can be thought as implementing generics, allows creation of types that reference other types
 * Useful for collection types, like lists
 */
export class ParametricDataType extends DataType {
    /**
     *
     * @type {DataType[]}
     */
    parameters = [];


    /**
     *
     * @param {number} id
     * @param {string} name
     * @param {DataType[]} [parameters]
     */
    set(id, name, parameters = []) {
        super.set(id, name);

        this.parameters = parameters;
    }

    /**
     *
     * @param {ParametricDataType} other
     * @returns {boolean}
     */
    equals(other) {
        if (other.isParametricDataType !== true) {
            return false;
        }

        return super.equals(other) && isArrayEqual(this.parameters, other.parameters);
    }

    toJSON() {
        const r = super.toJSON();

        r.parameters = this.parameters.map(p => p.toJSON());

        return r;
    }

    fromJSON(j) {
        super.fromJSON(j);

        this.parameters = j.parameters.map(deserializeDataTypeFromJSON);
    }

    /**
     * @param {number} id
     * @param {string} name
     * @param {DataType[]} [parameters]
     */
    static from(id, name, parameters = []) {

        const r = new ParametricDataType();

        r.set(id, name, parameters);

        return r;

    }

    /**
     *
     * @returns {boolean}
     */
    get isParametricDataType() {
        return true;
    }
}