/*---------------------------------------------------------------------------------------------
* Copyright (c) Bentley Systems, Incorporated. All rights reserved.
* See LICENSE.md in the project root for license terms and full copyright notice.
*--------------------------------------------------------------------------------------------*/
/** @packageDocumentation
 * @module Tiles
 */
import { assert, compareNumbers } from "@itwin/core-bentley";
import { Angle, AngleSweep, Range2d } from "@itwin/core-geometry";
import { Cartographic } from "@itwin/core-common";
const scratchCartographic1 = Cartographic.createZero();
const scratchCartographic2 = Cartographic.createZero();
/** Identifies a node within a [quad tree](https://en.wikipedia.org/wiki/Quadtree), such as a [[MapTile]] within a [[MapTileTree]].
 * A quad tree recursively sub-divides a two-dimensional space along the X and Y axes such that each node on level L has four child nodes on
 * level L+1.
 * @public
 */
export class QuadId {
    /** @alpha */
    get isValid() {
        return this.level >= 0;
    }
    /** @alpha */
    static createFromContentId(stringId) {
        const idParts = stringId.split("_");
        assert(idParts.length === 3);
        if (3 !== idParts.length)
            return new QuadId(-1, -1, -1);
        return new QuadId(parseInt(idParts[0], 10), parseInt(idParts[1], 10), parseInt(idParts[2], 10));
    }
    /** @alpha */
    get contentId() {
        return QuadId.getTileContentId(this.level, this.column, this.row);
    }
    /** @alpha */
    static getTileContentId(level, column, row) {
        return `${level}_${column}_${row}`;
    }
    /** @alpha */
    get debugString() {
        return `Level: ${this.level} Column: ${this.column} Row: ${this.row}`;
    }
    /** Construct a new QuadId. The inputs are expected to be non-negative integers. */
    constructor(level, column, row) {
        this.level = level;
        this.column = column;
        this.row = row;
    }
    /** Compute the QuadIds corresponding to this node's four child nodes. */
    getChildIds(columnCount = 2, rowCount = 2) {
        const childIds = [];
        const level = this.level + 1;
        const column = this.column * 2;
        const row = this.row * 2;
        for (let j = 0; j < rowCount; j++)
            for (let i = 0; i < columnCount; i++)
                childIds.push(new QuadId(level, column + i, row + j));
        return childIds;
    }
    /** Compute the region of the surface of the Earth represented by this node according to the specified tiling scheme. */
    getLatLongRangeDegrees(mapTilingScheme) {
        return this._getLatLongRange(mapTilingScheme, "degrees");
    }
    /** Compute the region of the surface of the Earth represented by this node according to the specified tiling scheme. */
    getLatLongRangeRadians(mapTilingScheme) {
        return this._getLatLongRange(mapTilingScheme, "radians");
    }
    _getLatLongRange(mapTilingScheme, units) {
        const range = Range2d.createNull();
        const factor = "degrees" === units ? Angle.degreesPerRadian : 1;
        mapTilingScheme.tileXYToCartographic(this.column, this.row, this.level, scratchCartographic1);
        range.extendXY(scratchCartographic1.longitude * factor, scratchCartographic1.latitude * factor);
        mapTilingScheme.tileXYToCartographic(this.column + 1, this.row + 1, this.level, scratchCartographic2);
        range.extendXY(scratchCartographic2.longitude * factor, scratchCartographic2.latitude * factor);
        return range;
    }
    /** @alpha */
    getAngleSweep(mapTilingScheme) {
        mapTilingScheme.tileXYToCartographic(this.column, this.row, this.level, scratchCartographic1);
        mapTilingScheme.tileXYToCartographic(this.column + 1, this.row + 1, this.level, scratchCartographic2);
        return {
            longitude: AngleSweep.createStartEndRadians(scratchCartographic1.longitude, scratchCartographic2.longitude),
            latitude: AngleSweep.createStartEndRadians(Cartographic.parametricLatitudeFromGeodeticLatitude(scratchCartographic1.latitude), Cartographic.parametricLatitudeFromGeodeticLatitude(scratchCartographic2.latitude)),
        };
    }
    /** Returns true if this node is adjacent to the south pole according to the specified tiling scheme. */
    bordersSouthPole(mapTilingScheme) {
        return mapTilingScheme.tileBordersSouthPole(this.row, this.level);
    }
    /** Returns true if this node is adjacent to the north pole according to the specified tiling scheme. */
    bordersNorthPole(mapTilingScheme) {
        return mapTilingScheme.tileBordersNorthPole(this.row, this.level);
    }
    /** Compares this Id to another according to the conventions of an [OrderedComparator]($bentley). */
    compare(other) {
        return compareNumbers(this.level, other.level) ||
            compareNumbers(this.row, other.row) ||
            compareNumbers(this.column, other.column);
    }
}
//# sourceMappingURL=QuadId.js.map