"use strict";
/*!
  Copyright 2018 Ron Buckton (rbuckton@chronicles.org)

  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.
 */
/** @module "iterable-query/fn" */
Object.defineProperty(exports, "__esModule", { value: true });
const tslib_1 = require("tslib");
const internal_1 = require("../internal");
const types_1 = require("../types");
const axis_1 = require("./axis");
const common_1 = require("./common");
function root(source, predicate = common_1.T) {
    internal_1.assert.mustBeHierarchyIterable(source, "source");
    internal_1.assert.mustBeFunctionOrUndefined(predicate, "predicate");
    return new RootTraversalIterable(source, predicate);
}
exports.root = root;
function ancestors(source, predicate = common_1.T) {
    internal_1.assert.mustBeHierarchyIterable(source, "source");
    internal_1.assert.mustBeFunctionOrUndefined(predicate, "predicate");
    return new AncestorsTraversalIterable(source, predicate);
}
exports.ancestors = ancestors;
function ancestorsAndSelf(source, predicate = common_1.T) {
    internal_1.assert.mustBeHierarchyIterable(source, "source");
    internal_1.assert.mustBeFunctionOrUndefined(predicate, "predicate");
    return new AncestorsAndSelfTraversalIterable(source, predicate);
}
exports.ancestorsAndSelf = ancestorsAndSelf;
function descendants(source, predicate = common_1.T) {
    internal_1.assert.mustBeHierarchyIterable(source, "source");
    internal_1.assert.mustBeFunctionOrUndefined(predicate, "predicate");
    return new DescendantsTraversalIterable(source, predicate);
}
exports.descendants = descendants;
function descendantsAndSelf(source, predicate = common_1.T) {
    internal_1.assert.mustBeHierarchyIterable(source, "source");
    internal_1.assert.mustBeFunctionOrUndefined(predicate, "predicate");
    return new DescendantsAndSelfTraversalIterable(source, predicate);
}
exports.descendantsAndSelf = descendantsAndSelf;
function parents(source, predicate = common_1.T) {
    internal_1.assert.mustBeHierarchyIterable(source, "source");
    internal_1.assert.mustBeFunctionOrUndefined(predicate, "predicate");
    return new ParentsTraversalIterable(source, predicate);
}
exports.parents = parents;
function self(source, predicate = common_1.T) {
    internal_1.assert.mustBeHierarchyIterable(source, "source");
    internal_1.assert.mustBeFunctionOrUndefined(predicate, "predicate");
    return new SelfTraversalIterable(source, predicate);
}
exports.self = self;
function siblings(source, predicate = common_1.T) {
    internal_1.assert.mustBeHierarchyIterable(source, "source");
    internal_1.assert.mustBeFunctionOrUndefined(predicate, "predicate");
    return new SiblingsTraversalIterable(source, predicate);
}
exports.siblings = siblings;
function siblingsAndSelf(source, predicate = common_1.T) {
    internal_1.assert.mustBeHierarchyIterable(source, "source");
    internal_1.assert.mustBeFunctionOrUndefined(predicate, "predicate");
    return new SiblingsAndSelfTraversalIterable(source, predicate);
}
exports.siblingsAndSelf = siblingsAndSelf;
function siblingsBeforeSelf(source, predicate = common_1.T) {
    internal_1.assert.mustBeHierarchyIterable(source, "source");
    internal_1.assert.mustBeFunctionOrUndefined(predicate, "predicate");
    return new SiblingsBeforeSelfTraversalIterable(source, predicate);
}
exports.siblingsBeforeSelf = siblingsBeforeSelf;
function siblingsAfterSelf(source, predicate = common_1.T) {
    internal_1.assert.mustBeHierarchyIterable(source, "source");
    internal_1.assert.mustBeFunctionOrUndefined(predicate, "predicate");
    return new SiblingsAfterSelfTraversalIterable(source, predicate);
}
exports.siblingsAfterSelf = siblingsAfterSelf;
function children(source, predicate = common_1.T) {
    internal_1.assert.mustBeHierarchyIterable(source, "source");
    internal_1.assert.mustBeFunctionOrUndefined(predicate, "predicate");
    return new ChildrenTraversalIterable(source, predicate);
}
exports.children = children;
function CreateTraversalIterable(tag, axis) {
    let HierarchyTraversalIterable = class HierarchyTraversalIterable {
        constructor(source, predicate) {
            this._source = source;
            this._predicate = predicate;
            this._axis = axis;
        }
        *[Symbol.iterator]() {
            const source = this._source;
            const hierarchy = internal_1.GetHierarchy(source);
            const predicate = this._predicate;
            const axis = this._axis;
            for (const element of source) {
                for (const related of axis(hierarchy, element)) {
                    if (predicate(related)) {
                        yield related;
                    }
                }
            }
        }
        [types_1.Hierarchical.hierarchy]() {
            return internal_1.GetHierarchy(this._source);
        }
    };
    HierarchyTraversalIterable = tslib_1.__decorate([
        internal_1.ToStringTag(tag)
    ], HierarchyTraversalIterable);
    return HierarchyTraversalIterable;
}
const RootTraversalIterable = CreateTraversalIterable("RootTraversalIterable", axis_1.Axis.root);
const AncestorsTraversalIterable = CreateTraversalIterable("AncestorsTraversalIterable", axis_1.Axis.ancestors);
const AncestorsAndSelfTraversalIterable = CreateTraversalIterable("AncestorsAndSelfTraversalIterable", axis_1.Axis.ancestorsAndSelf);
const DescendantsTraversalIterable = CreateTraversalIterable("DescendantsTraversalIterable", axis_1.Axis.descendants);
const DescendantsAndSelfTraversalIterable = CreateTraversalIterable("DescendantsAndSelfTraversalIterable", axis_1.Axis.descendantsAndSelf);
const ParentsTraversalIterable = CreateTraversalIterable("ParentsTraversalIterable", axis_1.Axis.parents);
const SelfTraversalIterable = CreateTraversalIterable("SelfTraversalIterable", axis_1.Axis.self);
const SiblingsTraversalIterable = CreateTraversalIterable("SiblingsTraversalIterable", axis_1.Axis.siblings);
const SiblingsAndSelfTraversalIterable = CreateTraversalIterable("SiblingsAndSelfTraversalIterable", axis_1.Axis.siblingsAndSelf);
const SiblingsBeforeSelfTraversalIterable = CreateTraversalIterable("SiblingsBeforeSelfTraversalIterable", axis_1.Axis.siblingsBeforeSelf);
const SiblingsAfterSelfTraversalIterable = CreateTraversalIterable("SiblingsAfterSelfTraversalIterable", axis_1.Axis.siblingsAfterSelf);
const ChildrenTraversalIterable = CreateTraversalIterable("ChildrenTraversalIterable", axis_1.Axis.children);
//# sourceMappingURL=traversal.js.map