"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.serialize = serialize;
const utils_1 = require("../utils");
class UnhandledTypeError extends TypeError {
    constructor(serializer, value) {
        super(`unhandled type: '${typeof value}' for serializer ${serializer.constructor.name}`);
    }
}
function serializeObject(serializer, obj, options) {
    for (const key in obj) {
        const name = (options === null || options === void 0 ? void 0 : options.getSerializationPropertyName(key)) || key;
        serializer.serializeEntry(name, obj[key]);
    }
    return serializer.end();
}
function serializeClass(serializer, value, options) {
    const name = value.constructor.name;
    const ser = serializer.serializeClass(name);
    return serializeObject(ser, value, options);
}
const defaultGetter = (value) => {
    var _a;
    return (_a = value.constructor[Symbol.metadata]) === null || _a === void 0 ? void 0 : _a.serde;
};
function serialize(serializer, value, optionsGetter = defaultGetter) {
    switch (typeof value) {
        case 'string': return serializer.serializeString(value);
        case 'number': return serializer.serializeNumber(value);
        case 'bigint': return serializer.serializeBigInt(value);
        case 'boolean': return serializer.serializeBoolean(value);
        case 'symbol': return serializer.serializeSymbol(value);
        case 'undefined': return serializer.serializeNull();
        case 'object':
            const options = optionsGetter(value);
            switch (true) {
                case value == null: return serializer.serializeNull();
                case !(0, utils_1.isPlainObject)(value): return serializeClass(serializer, value, options);
                default: return serializeObject(serializer.serializeObject(), value, options);
            }
        default: throw new UnhandledTypeError(serializer, value);
    }
}