"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.
 */
Object.defineProperty(exports, "__esModule", { value: true });
var tslib_1 = require("tslib");
var guards_1 = require("./guards");
var conversion_1 = require("./conversion");
var utils_1 = require("./utils");
var decorators_1 = require("./decorators");
var collections_1 = require("../collections");
/** @internal */ function FlowHierarchy(result, flowLeft, flowRight) {
    if (guards_1.IsPossiblyAsyncHierarchyIterable(result))
        return result;
    var leftHierarchy = guards_1.IsPossiblyAsyncHierarchyIterable(flowLeft) ? utils_1.GetHierarchy(flowLeft) : undefined;
    var rightHierarchy = guards_1.IsPossiblyAsyncHierarchyIterable(flowRight) ? utils_1.GetHierarchy(flowRight) : undefined;
    var hierarchy = CombineHierarchies(leftHierarchy, rightHierarchy);
    if (hierarchy) {
        if (guards_1.IsAsyncIterable(result)) {
            return conversion_1.MakeAsyncHierarchyIterable(result, hierarchy);
        }
    }
    return hierarchy ? guards_1.IsAsyncIterable(result) ? conversion_1.MakeAsyncHierarchyIterable(result, hierarchy) : conversion_1.MakeHierarchyIterable(result, hierarchy) : result;
}
exports.FlowHierarchy = FlowHierarchy;
/** @internal */ function CombineHierarchies(left, right) {
    var e_1, _a;
    if (left === right || right === undefined)
        return left;
    if (left === undefined)
        return right;
    var leftHierarchies = left instanceof CompositeHierarchyProvider ? left["_hierarchies"] : [left];
    var rightHierarchies = right instanceof CompositeHierarchyProvider ? right["_hierarchies"] : [right];
    var set = new collections_1.Set(leftHierarchies);
    try {
        for (var rightHierarchies_1 = tslib_1.__values(rightHierarchies), rightHierarchies_1_1 = rightHierarchies_1.next(); !rightHierarchies_1_1.done; rightHierarchies_1_1 = rightHierarchies_1.next()) {
            var hierarchy = rightHierarchies_1_1.value;
            set.add(hierarchy);
        }
    }
    catch (e_1_1) { e_1 = { error: e_1_1 }; }
    finally {
        try {
            if (rightHierarchies_1_1 && !rightHierarchies_1_1.done && (_a = rightHierarchies_1.return)) _a.call(rightHierarchies_1);
        }
        finally { if (e_1) throw e_1.error; }
    }
    if (set.size === leftHierarchies.length)
        return left;
    var hierarchies = tslib_1.__spread(set);
    return hierarchies.length === 1 ? hierarchies[0] : new CompositeHierarchyProvider(hierarchies);
}
exports.CombineHierarchies = CombineHierarchies;
var CompositeHierarchyProvider = /** @class */ (function () {
    function CompositeHierarchyProvider(hierarchies) {
        this._hierarchies = hierarchies;
    }
    CompositeHierarchyProvider.prototype.owns = function (value) {
        return findOwner(this._hierarchies, value) !== undefined;
    };
    CompositeHierarchyProvider.prototype.parent = function (value) {
        var hierarchy = findOwner(this._hierarchies, value);
        return hierarchy && hierarchy.parent(value);
    };
    CompositeHierarchyProvider.prototype.children = function (value) {
        var hierarchy = findOwner(this._hierarchies, value);
        return hierarchy ? hierarchy.children(value) : [];
    };
    CompositeHierarchyProvider = tslib_1.__decorate([
        decorators_1.ToStringTag("CompositeHierarchyProvider")
    ], CompositeHierarchyProvider);
    return CompositeHierarchyProvider;
}());
function findOwner(hierarchies, value) {
    var e_2, _a;
    var bestMatch;
    try {
        for (var hierarchies_1 = tslib_1.__values(hierarchies), hierarchies_1_1 = hierarchies_1.next(); !hierarchies_1_1.done; hierarchies_1_1 = hierarchies_1.next()) {
            var hierarchy = hierarchies_1_1.value;
            if (hierarchy.owns) {
                if (hierarchy.owns(value))
                    return hierarchy;
            }
            else if (!bestMatch) {
                bestMatch = hierarchy;
            }
        }
    }
    catch (e_2_1) { e_2 = { error: e_2_1 }; }
    finally {
        try {
            if (hierarchies_1_1 && !hierarchies_1_1.done && (_a = hierarchies_1.return)) _a.call(hierarchies_1);
        }
        finally { if (e_2) throw e_2.error; }
    }
    return bestMatch;
}
//# sourceMappingURL=flow.js.map