"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.V1MessageWriter = void 0;
var ContextError_1 = require("../../error/ContextError");
var V1MessageWriter = /** @class */ (function () {
    /**
     * Delta publisher
     *
     * @param _encoder_ctr - a factory function to create an avro encoder
     * @param _conn        - the amqp connection
     */
    function V1MessageWriter(_encoder_ctor, _schema) {
        this._encoder_ctor = _encoder_ctor;
        this._schema = _schema;
        /** A mapping of which delta type translated to which avro event */
        this.DELTA_MAP = {
            data: 'STEP_SAVE',
            ratedata: 'RATE',
        };
    }
    /**
     * Write the data to a message
     *
     * @param ts       - timestamp
     * @param meta     - document meta data
     * @param delta    - current delta
     * @param bucket   - data bucket
     * @param ratedata - ratedata bucket
     */
    V1MessageWriter.prototype.write = function (ts, meta, delta, bucket, ratedata) {
        var avro_object = this._avroFormat(ts, meta, delta, bucket, ratedata);
        return this.avroEncode(avro_object);
    };
    /**
     * Format the avro data with data type labels
     *
     * @param ts       - timestamp
     * @param meta     - document meta data
     * @param delta    - current delta
     * @param bucket   - data bucket
     * @param ratedata - ratedata bucket
     *
     * @return the formatted data
     */
    V1MessageWriter.prototype._avroFormat = function (ts, meta, delta, bucket, ratedata) {
        var delta_formatted = this.setDataTypes(delta.data);
        var bucket_formatted = this.setDataTypes(bucket);
        var ratedata_formatted = this.setDataTypes(ratedata);
        var event_id = this.DELTA_MAP[delta.type];
        var start_date_ms = { long: meta.startDate * 1000 };
        var last_update_ms = { long: meta.lastUpdate * 1000 };
        var exp_date_ms = { long: meta.expDate };
        var ts_ms = ts * 1000;
        var step = null;
        if (delta.concluding_save === true) {
            step = {
                EventStep: {
                    transition: 'END',
                    src: '',
                    dest: '',
                },
            };
        }
        return {
            event: {
                id: event_id,
                ts: ts_ms,
                actor: 'SERVER',
                step: step,
            },
            document: {
                id: meta.id,
                quote_set_id: meta.quoteSetId,
                created: start_date_ms,
                modified: last_update_ms,
                expires: exp_date_ms,
            },
            session: {
                Session: {
                    entity_id: meta.entity_id,
                    entity_name: meta.entity_name,
                },
            },
            data: {
                Data: {
                    bucket: bucket_formatted,
                },
            },
            ratedata: {
                Data: {
                    bucket: ratedata_formatted,
                },
            },
            delta: {
                Data: {
                    bucket: delta_formatted,
                },
            },
            program: {
                Program: {
                    id: meta.program,
                    version: '',
                },
            },
        };
    };
    /**
     * Encode the data in an avro buffer
     *
     * @param data - the data to encode
     *
     * @return the avro buffer or null if there is an error
     */
    V1MessageWriter.prototype.avroEncode = function (data) {
        var _this = this;
        return new Promise(function (resolve, reject) {
            var bufs = [];
            try {
                _this._schema.isValid(data, {
                    errorHook: function (keys, vals) {
                        throw ContextError_1.context(new Error('Invalid Avro Schema'), {
                            invalid_paths: keys,
                            invalid_data: vals,
                        });
                    },
                });
                var encoder = _this._encoder_ctor(_this._schema);
                encoder.on('data', function (buf) {
                    bufs.push(buf);
                });
                encoder.on('error', function (err) {
                    reject(err);
                });
                encoder.on('end', function () {
                    resolve(Buffer.concat(bufs));
                });
                encoder.end(data);
            }
            catch (e) {
                reject(e);
            }
        });
    };
    /**
     * Format the data for avro by add type specifications to the data
     *
     * @param data      - the data to format
     * @param top_level - whether we are at the top level of the recursion
     *
     * @return the formatted data
     */
    V1MessageWriter.prototype.setDataTypes = function (data, top_level) {
        var _this = this;
        if (top_level === void 0) { top_level = true; }
        var data_formatted = {};
        switch (typeof data) {
            case 'object':
                if (data == null) {
                    return null;
                }
                else if (Array.isArray(data)) {
                    var arr_1 = [];
                    data.forEach(function (datum) {
                        arr_1.push(_this.setDataTypes(datum, false));
                    });
                    data_formatted = top_level ? arr_1 : { array: arr_1 };
                }
                else {
                    var datum_formatted_1 = {};
                    Object.keys(data).forEach(function (key) {
                        // Do not include "private" keys
                        if (key.startsWith('__')) {
                            return;
                        }
                        var datum = _this.setDataTypes(data[key], false);
                        datum_formatted_1[key] = datum;
                    });
                    data_formatted = top_level ? datum_formatted_1 : { map: datum_formatted_1 };
                }
                break;
            case 'boolean':
                return { boolean: data };
            case 'number':
                return { double: data };
            case 'string':
                return { string: data };
            case 'undefined':
                return null;
        }
        return data_formatted;
    };
    return V1MessageWriter;
}());
exports.V1MessageWriter = V1MessageWriter;
//# sourceMappingURL=data:application/json;base64, 