/*---------------------------------------------------------------------------------------------
* Copyright (c) Bentley Systems, Incorporated. All rights reserved.
* See LICENSE.md in the project root for license terms and full copyright notice.
*--------------------------------------------------------------------------------------------*/
/** @packageDocumentation
 * @module RangeSearch
 */
import { Range2d } from "../../geometry3d/Range";
import { GriddedRaggedRange2dSet } from "./GriddedRaggedRange2dSet";
import { LinearSearchRange2dArray } from "./LinearSearchRange2dArray";
/**
 * Use GriddedRaggedRange2dSetWithOverflow for searching among many ranges for which:
 * * Most ranges are of somewhat consistent size.
 * * A modest number of oversizes.
 * * Maintain the smallish ones in a GriddedRaggedRange2dSet.
 * * Maintain the overflows in a Range2dSearchInterface.
 * @public
 */
export class GriddedRaggedRange2dSetWithOverflow {
    _gridSet;
    _overflowSet;
    static _workRange;
    constructor(gridSet, overflowSet) {
        this._gridSet = gridSet;
        this._overflowSet = overflowSet;
    }
    /**
     * Create an (empty) set of ranges.
     * @param range
     * @param numXEdge
     * @param numYEdge
     */
    static create(range, numXEdge, numYEdge) {
        const grids = GriddedRaggedRange2dSet.create(range.clone(), numXEdge, numYEdge);
        if (grids)
            return new GriddedRaggedRange2dSetWithOverflow(grids, new LinearSearchRange2dArray());
        return undefined;
    }
    /**
     * * Search for ranges containing testRange
     * * Pass each range and tag to handler
     * * terminate search if handler returns false.
     * @param testRange search range.
     * @param handler function to receive range and tag hits.
     * @return false if search terminated by handler.  Return true if no handler returned false.
     */
    searchXY(x, y, handler) {
        return this._gridSet.searchXY(x, y, handler) && this._overflowSet.searchXY(x, y, handler);
    }
    /**
     * * Search for ranges overlapping testRange
     * * Pass each range and tag to handler
     * * terminate search if handler returns false.
     * @param testRange search range.
     * @param handler function to receive range and tag hits.
     * @return false if search terminated by handler.  Return true if no handler returned false.
     */
    searchRange2d(testRange, handler) {
        return this._gridSet.searchRange2d(testRange, handler) && this._overflowSet.searchRange2d(testRange, handler);
    }
    /** If possible, insert a range into the set.
     * * Decline to insert (and return false) if
     *   * range is null
     *   * range is not completely contained in the overall range of this set.
     *   * range x or y extent is larger than 2 grid blocks.
     */
    addRange(range, tag) {
        if (!Range2d.isNull(range)) {
            if (!this._gridSet.conditionalInsert(range, tag))
                this._overflowSet.addRange(range, tag);
        }
    }
    /** Return the overall range of all members. */
    totalRange(result) {
        if (result)
            result.setNull();
        else
            result = Range2d.createNull();
        this.visitChildren(0, (_depth, child) => {
            const childRange = GriddedRaggedRange2dSetWithOverflow._workRange = child.totalRange(GriddedRaggedRange2dSetWithOverflow._workRange);
            result.extendRange(childRange);
        });
        return result;
    }
    /** Call the handler on the overflow set, and on each defined block in the grid. */
    visitChildren(initialDepth, handler) {
        handler(initialDepth, this._overflowSet);
        this._gridSet.visitChildren(initialDepth + 1, handler);
    }
}
//# sourceMappingURL=GriddedRaggedRange2dSetWithOverflow.js.map