export const inversions = {
    from: 'out',
    to: 'in',
    type: 'typed',
    out: 'from',
    in: 'to',
    typed: 'type',
    up: 'down',
    down: 'up',
};
export class Traveler {
    constructor(deep, links = [], travels = [], mode = 'remote') {
        this.links = [];
        this.mode = 'remote';
        this.deep = deep;
        this.links = links;
        this.travels = travels;
        this.mode = mode;
    }
    from(query) {
        return new Traveler(this.deep, this.links, [...this.travels, { query: query, direction: 'from' }], this.mode);
    }
    to(query) {
        return new Traveler(this.deep, this.links, [...this.travels, { query: query, direction: 'to' }], this.mode);
    }
    type(query) {
        return new Traveler(this.deep, this.links, [...this.travels, { query: query, direction: 'type' }], this.mode);
    }
    out(query) {
        return new Traveler(this.deep, this.links, [...this.travels, { query: query, direction: 'out' }], this.mode);
    }
    in(query) {
        return new Traveler(this.deep, this.links, [...this.travels, { query: query, direction: 'in' }], this.mode);
    }
    typed(query) {
        return new Traveler(this.deep, this.links, [...this.travels, { query: query, direction: 'typed' }], this.mode);
    }
    up(query) {
        return new Traveler(this.deep, this.links, [...this.travels, { query: query, direction: 'up' }], this.mode);
    }
    down(query) {
        return new Traveler(this.deep, this.links, [...this.travels, { query: query, direction: 'down' }], this.mode);
    }
    and(query) {
        return new Traveler(this.deep, this.links, [...this.travels, { query: query }], this.mode);
    }
    get query() {
        let current = { id: { _in: this.links.map(l => l.id) } };
        for (let t = 0; t < this.travels.length; t++) {
            const travel = this.travels[t];
            if (!travel.direction) {
                current = { _and: [(travel.query || {}), current] };
            }
            else if (['up', 'down'].includes(inversions[travel.direction])) {
                current = {
                    [inversions[travel.direction]]: Object.assign(Object.assign({}, (travel.query || {})), { [inversions[travel.direction] === 'down' ? 'link' : 'parent']: current }),
                };
            }
            else {
                current = Object.assign(Object.assign({}, (travel.query || {})), { [inversions[travel.direction]]: current });
            }
        }
        return current;
    }
    select() {
        const query = this.query;
        if (this.mode === 'remote') {
            return this.deep.select(query);
        }
        else {
            return this.deep.minilinks.select(query);
        }
    }
    subscription() {
        const query = this.query;
        if (this.mode === 'remote') {
            return this.deep.subscribe(query);
        }
        else {
            return this.deep.minilinks.subscribe(query);
        }
    }
    count() {
        var _a;
        const query = this.query;
        if (this.mode === 'remote') {
            return this.deep.select(query, { aggregate: 'count' });
        }
        else {
            return (_a = this.deep.minilinks.select(query)) === null || _a === void 0 ? void 0 : _a.length;
        }
    }
    sum() {
        const query = this.query;
        if (this.mode === 'remote') {
            return this.deep.select(query, { aggregate: 'sum' });
        }
        else {
        }
    }
    avg() {
        const query = this.query;
        if (this.mode === 'remote') {
            return this.deep.select(query, { aggregate: 'avg' });
        }
        else {
        }
    }
    min() {
        const query = this.query;
        if (this.mode === 'remote') {
            return this.deep.select(query, { aggregate: 'min' });
        }
        else {
        }
    }
    max() {
        const query = this.query;
        if (this.mode === 'remote') {
            return this.deep.select(query, { aggregate: 'max' });
        }
        else {
        }
    }
    get local() {
        return new Traveler(this.deep, this.links, this.travels, 'local');
    }
    get remote() {
        return new Traveler(this.deep, this.links, this.travels, 'remote');
    }
}
//# sourceMappingURL=traveler.js.map