"use strict";
/*
 * Copyright 2016 Teppo Kurki <teppo.kurki@iki.fi>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0

 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
    var ownKeys = function(o) {
        ownKeys = Object.getOwnPropertyNames || function (o) {
            var ar = [];
            for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
            return ar;
        };
        return ownKeys(o);
    };
    return function (mod) {
        if (mod && mod.__esModule) return mod;
        var result = {};
        if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
        __setModuleDefault(result, mod);
        return result;
    };
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.StreamBundle = void 0;
exports.toDelta = toDelta;
const Bacon = __importStar(require("baconjs"));
class StreamBundle {
    selfContext;
    buses;
    allPathsBus;
    selfBuses;
    selfAllPathsBus;
    selfStreams;
    selfAllPathsStream;
    keys;
    availableSelfPaths;
    metaBus;
    selfMetaBus;
    constructor(selfId) {
        this.selfContext = 'vessels.' + selfId;
        this.buses = {};
        this.allPathsBus = new Bacon.Bus();
        this.selfBuses = {};
        this.selfAllPathsBus = new Bacon.Bus();
        this.selfStreams = {};
        this.selfAllPathsStream = new Bacon.Bus();
        this.keys = new Bacon.Bus();
        this.availableSelfPaths = {};
        this.metaBus = new Bacon.Bus();
        this.selfMetaBus = new Bacon.Bus();
    }
    pushDelta(delta) {
        try {
            if (!delta.updates) {
                return;
            }
            // TSTODO: the ! coercions below cover optional fields that are required
            // here; tighten the Delta types when possible.
            const context = delta.context;
            for (const update of delta.updates) {
                const source = update.source;
                const $source = update.$source;
                const timestamp = update.timestamp;
                if ('meta' in update) {
                    for (const meta of update.meta) {
                        // Build the NormalizedDelta in its final shape with a stable key
                        // order across both branches so V8 can reuse one hidden class.
                        this.push(meta.path, {
                            context,
                            source,
                            $source,
                            timestamp,
                            path: meta.path,
                            value: meta.value,
                            isMeta: true
                        });
                    }
                }
                if ('values' in update) {
                    for (const pathValue of update.values) {
                        this.push(pathValue.path, {
                            context,
                            source,
                            $source,
                            timestamp,
                            path: pathValue.path,
                            value: pathValue.value,
                            isMeta: false
                        });
                    }
                }
            }
        }
        catch (e) {
            console.error(e);
        }
    }
    push(path, normalizedDelta) {
        const { isMeta } = normalizedDelta;
        const isSelf = normalizedDelta.context === this.selfContext;
        if (isMeta) {
            this.metaBus.push(normalizedDelta);
            if (isSelf) {
                this.selfMetaBus.push(normalizedDelta);
            }
        }
        if (!this.availableSelfPaths[path]) {
            this.availableSelfPaths[path] = true;
        }
        this.getBus().push(normalizedDelta);
        this.getBus(path).push(normalizedDelta);
        if (isSelf) {
            this.getSelfBus().push(normalizedDelta);
            this.getSelfBus(path).push(normalizedDelta);
            if (!isMeta) {
                this.getSelfStream().push(normalizedDelta.value);
                this.getSelfStream(path).push(normalizedDelta.value);
            }
        }
    }
    getMetaBus() {
        return this.metaBus;
    }
    getSelfMetaBus() {
        return this.selfMetaBus;
    }
    getBus(path) {
        if (path !== undefined) {
            let result = this.buses[path];
            if (!result) {
                result = this.buses[path] = new Bacon.Bus();
                this.keys.push(path);
            }
            return result;
        }
        else {
            return this.allPathsBus;
        }
    }
    getSelfStream(path) {
        if (path !== undefined) {
            let result = this.selfStreams[path];
            if (!result) {
                result = this.selfStreams[path] = new Bacon.Bus();
            }
            return result;
        }
        else {
            return this.selfAllPathsStream;
        }
    }
    getSelfBus(path) {
        if (path !== undefined) {
            let result = this.selfBuses[path];
            if (!result) {
                result = this.selfBuses[path] = new Bacon.Bus();
            }
            return result;
        }
        else {
            return this.selfAllPathsBus;
        }
    }
    getAvailablePaths() {
        return Object.keys(this.availableSelfPaths);
    }
}
exports.StreamBundle = StreamBundle;
function toDelta(normalizedDeltaData) {
    const type = normalizedDeltaData.isMeta ? 'meta' : 'values';
    const update = {
        source: normalizedDeltaData.source,
        $source: normalizedDeltaData.$source,
        timestamp: normalizedDeltaData.timestamp,
        [type]: [
            {
                path: normalizedDeltaData.path,
                value: normalizedDeltaData.value
            }
        ]
    };
    return {
        context: normalizedDeltaData.context,
        updates: [update]
    };
}
//# sourceMappingURL=streambundle.js.map