import { Bounds, Epsg, GoogleTms, ImageFormat, Nztm2000QuadTms, Nztm2000Tms } from '@basemaps/geo';
import { TileSetName, V, VNodeElement } from '@basemaps/shared';
import { roundNumbersInString } from '@basemaps/test/build/rounding.js';
import { createHash } from 'crypto';
import o from 'ospec';
import { WmtsCapabilities } from '../wmts.capability.js';
import { FakeTileSet, Provider } from './xyz.util.js';
import 'source-map-support/register.js';
function tags(node, tag) {
    if (node == null)
        return [];
    return [...node.tags(tag)];
}
function listTag(node, tag) {
    return tags(node, tag).map((n) => n.toString());
}
o.spec('WmtsCapabilities', () => {
    const apiKey = 'secret1234';
    const tileSet = new FakeTileSet(TileSetName.aerial, GoogleTms);
    const tileSetImagery = new FakeTileSet('01E7PJFR9AMQFJ05X9G7FQ3XMW', GoogleTms);
    o('should output the requested formats', () => {
        const wmts = new WmtsCapabilities({
            httpBase: 'https://basemaps.test',
            provider: Provider,
            layers: [tileSet],
            apiKey,
            formats: [ImageFormat.Avif],
        }).toVNode();
        const urls = tags(wmts, 'ResourceURL');
        o(urls.length).equals(1);
        o(urls[0].attrs.format).equals('image/avif');
        o(urls[0].attrs.template).equals('https://basemaps.test/v1/tiles/aerial/{TileMatrixSet}/{TileMatrix}/{TileCol}/{TileRow}.avif?api=secret1234');
    });
    o('should build capability xml for tileset and projection', () => {
        var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l;
        const wmts = new WmtsCapabilities({
            httpBase: 'https://basemaps.test',
            provider: Provider,
            layers: [tileSet],
            apiKey,
        });
        const raw = wmts.toVNode();
        const serviceId = raw.find('ows:ServiceIdentification');
        o((_a = serviceId === null || serviceId === void 0 ? void 0 : serviceId.find('ows:Abstract')) === null || _a === void 0 ? void 0 : _a.textContent).equals('the description');
        o((_b = serviceId === null || serviceId === void 0 ? void 0 : serviceId.find('ows:Title')) === null || _b === void 0 ? void 0 : _b.textContent).equals('the title');
        o((_c = raw.find('TileMatrixSetLink')) === null || _c === void 0 ? void 0 : _c.toString()).deepEquals(V('TileMatrixSetLink', [V('TileMatrixSet', 'EPSG:3857')]).toString());
        const layer = raw === null || raw === void 0 ? void 0 : raw.find('Contents', 'Layer');
        o(listTag(layer, 'Format')).deepEquals([
            V('Format', 'image/jpeg').toString(),
            V('Format', 'image/webp').toString(),
            V('Format', 'image/png').toString(),
        ]);
        o(listTag(layer, 'ows:BoundingBox')).deepEquals([
            V('ows:BoundingBox', { crs: Epsg.Google.toUrn() }, [
                V('ows:LowerCorner', '-20037508.3427892 -20037508.3427892'),
                V('ows:UpperCorner', '20037508.3427892 20037508.3427892'),
            ]).toString(),
        ]);
        o(listTag(layer, 'ows:WGS84BoundingBox').map((s) => roundNumbersInString(s, 4))).deepEquals([
            '<ows:WGS84BoundingBox crs="urn:ogc:def:crs:OGC:2:84">\n' +
                '  <ows:LowerCorner>-180 -85.0511</ows:LowerCorner>\n' +
                '  <ows:UpperCorner>180 85.0511</ows:UpperCorner>\n' +
                '</ows:WGS84BoundingBox>',
        ]);
        o((_d = layer === null || layer === void 0 ? void 0 : layer.find('ows:Abstract')) === null || _d === void 0 ? void 0 : _d.textContent).equals('aerial:description');
        o((_e = layer === null || layer === void 0 ? void 0 : layer.find('ows:Title')) === null || _e === void 0 ? void 0 : _e.textContent).equals('aerial:title');
        o((_f = layer === null || layer === void 0 ? void 0 : layer.find('ows:Identifier')) === null || _f === void 0 ? void 0 : _f.textContent).equals('aerial');
        o((_g = layer === null || layer === void 0 ? void 0 : layer.find('Style')) === null || _g === void 0 ? void 0 : _g.toString()).equals(V('Style', { isDefault: 'true' }, [V('ows:Title', 'Default Style'), V('ows:Identifier', 'default')]).toString());
        const urls = tags(layer, 'ResourceURL');
        o(urls.length).equals(3);
        o(urls[2].toString()).deepEquals('<ResourceURL format="image/png" resourceType="tile" ' +
            'template="https://basemaps.test/v1/tiles/aerial/{TileMatrixSet}/{TileMatrix}/{TileCol}/{TileRow}.png?api=secret1234" />');
        o((_h = layer === null || layer === void 0 ? void 0 : layer.find('TileMatrixSetLink', 'TileMatrixSet')) === null || _h === void 0 ? void 0 : _h.textContent).equals('EPSG:3857');
        const matrix = tags(raw, 'TileMatrixSet')[1];
        const matrixId = (_j = raw === null || raw === void 0 ? void 0 : raw.find('Contents', 'TileMatrixSet', 'ows:Identifier')) !== null && _j !== void 0 ? _j : null;
        o(matrix.find('ows:Identifier')).equals(matrixId);
        o(matrixId === null || matrixId === void 0 ? void 0 : matrixId.textContent).equals('EPSG:3857');
        o((_k = matrix.find('ows:SupportedCRS')) === null || _k === void 0 ? void 0 : _k.textContent).deepEquals('urn:ogc:def:crs:EPSG::3857');
        o((_l = matrix.find('WellKnownScaleSet')) === null || _l === void 0 ? void 0 : _l.textContent).deepEquals('https://www.opengis.net/def/wkss/OGC/1.0/GoogleMapsCompatible');
        const tileMatrices = Array.from(matrix.tags('TileMatrix'));
        o(tileMatrices.length).equals(25);
        function compareMatrix(x, id, tileCount, scale) {
            var _a, _b, _c, _d, _e, _f, _g;
            o((_a = x.find('ows:Identifier')) === null || _a === void 0 ? void 0 : _a.toString()).equals(`<ows:Identifier>${id}</ows:Identifier>`);
            o((_b = x.find('ScaleDenominator')) === null || _b === void 0 ? void 0 : _b.toString()).equals(`<ScaleDenominator>${scale}</ScaleDenominator>`);
            o((_c = x.find('TopLeftCorner')) === null || _c === void 0 ? void 0 : _c.toString()).equals(`<TopLeftCorner>-20037508.3427892 20037508.3427892</TopLeftCorner>`);
            o((_d = x.find('TileWidth')) === null || _d === void 0 ? void 0 : _d.toString()).equals(`<TileWidth>256</TileWidth>`);
            o((_e = x.find('TileHeight')) === null || _e === void 0 ? void 0 : _e.toString()).equals(`<TileHeight>256</TileHeight>`);
            o((_f = x.find('MatrixWidth')) === null || _f === void 0 ? void 0 : _f.toString()).equals(`<MatrixWidth>${tileCount}</MatrixWidth>`);
            o((_g = x.find('MatrixHeight')) === null || _g === void 0 ? void 0 : _g.toString()).equals(`<MatrixHeight>${tileCount}</MatrixHeight>`);
        }
        compareMatrix(tileMatrices[0], '0', 1, 559082264.028717);
        compareMatrix(tileMatrices[10], '10', 1024, 545978.773465544);
        const xml = new WmtsCapabilities({
            httpBase: 'https://basemaps.test',
            provider: Provider,
            layers: [tileSet],
            apiKey,
        }).toXml();
        o(xml).deepEquals('<?xml version="1.0"?>\n' + (raw === null || raw === void 0 ? void 0 : raw.toString()));
        o(createHash('sha256').update(Buffer.from(xml)).digest('base64')).equals('beknYyMt8v74vK4p84AS3c1OnBSJ+ZE0kan+mMVQS1A=');
    });
    o('should allow individual imagery sets', () => {
        const raw = new WmtsCapabilities({
            httpBase: 'https://basemaps.test',
            provider: Provider,
            layers: [tileSetImagery],
        }).toVNode();
        const tms = raw === null || raw === void 0 ? void 0 : raw.find('TileMatrixSet', 'ows:Identifier');
        o(tms === null || tms === void 0 ? void 0 : tms.textContent).equals('EPSG:3857');
        const urls = Array.from(raw ? raw.tags('ResourceURL') : []);
        o(urls.length).equals(3);
        o(urls[2].toString()).deepEquals('<ResourceURL format="image/png" resourceType="tile" ' +
            'template="https://basemaps.test/v1/tiles/01E7PJFR9AMQFJ05X9G7FQ3XMW/{TileMatrixSet}/{TileMatrix}/{TileCol}/{TileRow}.png" />');
    });
    o('should support multiple projections', () => {
        var _a, _b, _c, _d;
        const ts = [new FakeTileSet(TileSetName.aerial, Nztm2000Tms), new FakeTileSet(TileSetName.aerial, GoogleTms)];
        const xml = new WmtsCapabilities({ httpBase: 'basemaps.test', provider: Provider, layers: ts });
        const nodes = xml.toVNode();
        const layers = tags(nodes, 'Layer');
        o(layers.length).equals(1);
        const layer = layers[0];
        // ensure order is valid
        o(layer === null || layer === void 0 ? void 0 : layer.children.map((c) => (c instanceof VNodeElement ? c.tag : null))).deepEquals([
            'ows:Title',
            'ows:Abstract',
            'ows:Identifier',
            'ows:BoundingBox',
            'ows:BoundingBox',
            'ows:WGS84BoundingBox',
            'Style',
            'Format',
            'Format',
            'Format',
            'TileMatrixSetLink',
            'TileMatrixSetLink',
            'ResourceURL',
            'ResourceURL',
            'ResourceURL',
        ]);
        const sets = tags(layer, 'TileMatrixSet');
        o(sets.length).equals(2);
        o(sets[0].toString()).equals('<TileMatrixSet>EPSG:2193</TileMatrixSet>');
        o(sets[1].toString()).equals('<TileMatrixSet>EPSG:3857</TileMatrixSet>');
        const tms = tags(nodes, 'TileMatrixSet').filter((f) => f.find('ows:SupportedCRS') != null);
        o(tms.length).equals(2);
        o((_a = tms[0].find('ows:Identifier')) === null || _a === void 0 ? void 0 : _a.textContent).equals('EPSG:2193');
        o((_b = tms[0].find('ows:SupportedCRS')) === null || _b === void 0 ? void 0 : _b.textContent).equals('urn:ogc:def:crs:EPSG::2193');
        o((_c = tms[1].find('ows:Identifier')) === null || _c === void 0 ? void 0 : _c.textContent).equals('EPSG:3857');
        o((_d = tms[1].find('ows:SupportedCRS')) === null || _d === void 0 ? void 0 : _d.textContent).equals('urn:ogc:def:crs:EPSG::3857');
    });
    o('should support multiple tilesets', () => {
        var _a, _b, _c, _d;
        const ts = [
            new FakeTileSet(TileSetName.aerial, Nztm2000Tms, 'aerial-title'),
            new FakeTileSet('01E7PJFR9AMQFJ05X9G7FQ3XMW', Nztm2000Tms, 'imagery-title'),
        ];
        const nodes = new WmtsCapabilities({ httpBase: 'basemaps.test', provider: Provider, layers: ts }).toVNode();
        const layers = tags(nodes, 'Layer');
        o(layers.length).equals(2);
        o((_a = layers[0].find('ows:Title')) === null || _a === void 0 ? void 0 : _a.textContent).equals('aerial-title');
        o((_b = layers[0].find('TileMatrixSet')) === null || _b === void 0 ? void 0 : _b.textContent).equals('EPSG:2193');
        o((_c = layers[1].find('ows:Title')) === null || _c === void 0 ? void 0 : _c.textContent).equals('imagery-title');
        o((_d = layers[1].find('TileMatrixSet')) === null || _d === void 0 ? void 0 : _d.textContent).equals('EPSG:2193');
    });
    o('should support child tile sets', () => {
        const ts = [
            new FakeTileSet(`${TileSetName.aerial}:wairoa_urban_2014-2015_0-10m_RGBA`, Nztm2000Tms, 'wairoa_urban_2014-2015_0-10m_RGBA'),
            new FakeTileSet(`${TileSetName.aerial}:west-coast_rural_2016-17_0-3m`, Nztm2000Tms, 'west-coast_rural_2016-17_0-3m'),
        ];
        const nodes = new WmtsCapabilities({ httpBase: 'basemaps.test', provider: Provider, layers: ts }).toVNode();
        const layers = tags(nodes, 'Layer');
        o(layers.length).equals(2);
        const boundingBoxes = tags(layers[0], 'ows:BoundingBox');
        o(boundingBoxes.length).equals(1);
        const firstTitle = layers[0].children[0].textContent;
        o(firstTitle).equals('wairoa_urban_2014-2015_0-10m_RGBA');
        const secondTitle = layers[1].children[0].textContent;
        o(secondTitle).equals('west-coast_rural_2016-17_0-3m');
    });
    o('should support multiple different projections on different tiles sets', () => {
        var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m;
        const ts = [
            new FakeTileSet(TileSetName.aerial, Nztm2000Tms, TileSetName.aerial),
            new FakeTileSet('01F75X9G7FQ3XMWPJFR9AMQFJ0', Nztm2000Tms, '01F75X9G7FQ3XMWPJFR9AMQFJ0'),
            new FakeTileSet('01E7PJFR9AMQFJ05X9G7FQ3XMW', GoogleTms, '01E7PJFR9AMQFJ05X9G7FQ3XMW'),
            new FakeTileSet('01E7PJFR9AMQFJ05X9G7FQ3XMW', Nztm2000QuadTms, '01E7PJFR9AMQFJ05X9G7FQ3XMW'),
        ];
        ts[1].extentOverride = new Bounds(1, 2, 2, 2);
        ts[2].tileSet.title = 'aerial_dunedin_urban';
        const nodes = new WmtsCapabilities({ httpBase: 'basemaps.test', provider: Provider, layers: ts }).toVNode();
        const allMatrixes = tags(nodes, 'TileMatrixSet');
        o(allMatrixes[0].children[0].textContent).equals('EPSG:2193');
        o(allMatrixes[1].children[0].textContent).equals('EPSG:2193');
        o(allMatrixes[2].children[0].textContent).equals('EPSG:3857');
        o(allMatrixes[3].children[0].textContent).equals('NZTM2000Quad');
        o((_a = allMatrixes[4].find('ows:Identifier')) === null || _a === void 0 ? void 0 : _a.textContent).equals('EPSG:2193');
        o((_b = allMatrixes[5].find('ows:Identifier')) === null || _b === void 0 ? void 0 : _b.textContent).equals('EPSG:3857');
        o((_c = allMatrixes[6].find('ows:Identifier')) === null || _c === void 0 ? void 0 : _c.textContent).equals('NZTM2000Quad');
        o(allMatrixes.length).equals(7);
        const layers = tags(nodes, 'Layer');
        o(layers.length).equals(3);
        o((_d = layers[0].find('ows:Title')) === null || _d === void 0 ? void 0 : _d.textContent).equals(TileSetName.aerial);
        o((_e = layers[0].find('TileMatrixSet')) === null || _e === void 0 ? void 0 : _e.textContent).equals('EPSG:2193');
        o((_f = layers[1].find('ows:Identifier')) === null || _f === void 0 ? void 0 : _f.textContent).equals('01F75X9G7FQ3XMWPJFR9AMQFJ0');
        o((_g = layers[1].find('TileMatrixSet')) === null || _g === void 0 ? void 0 : _g.textContent).equals('EPSG:2193');
        o((_h = layers[1].find('ows:BoundingBox')) === null || _h === void 0 ? void 0 : _h.toString()).equals('<ows:BoundingBox crs="urn:ogc:def:crs:EPSG::2193">\n' +
            '  <ows:LowerCorner>2 1</ows:LowerCorner>\n' +
            '  <ows:UpperCorner>4 3</ows:UpperCorner>\n' +
            '</ows:BoundingBox>');
        o((_j = layers[2].find('ows:Title')) === null || _j === void 0 ? void 0 : _j.textContent).equals('aerial_dunedin_urban');
        o((_k = layers[2].find('ows:Identifier')) === null || _k === void 0 ? void 0 : _k.textContent).equals('01E7PJFR9AMQFJ05X9G7FQ3XMW');
        o((_l = layers[2].find('TileMatrixSet')) === null || _l === void 0 ? void 0 : _l.textContent).equals('EPSG:3857');
        o((_m = layers[2].find('ows:BoundingBox')) === null || _m === void 0 ? void 0 : _m.toString()).equals('<ows:BoundingBox crs="urn:ogc:def:crs:EPSG::3857">\n' +
            '  <ows:LowerCorner>-20037508.3427892 -20037508.3427892</ows:LowerCorner>\n' +
            '  <ows:UpperCorner>20037508.3427892 20037508.3427892</ows:UpperCorner>\n' +
            '</ows:BoundingBox>');
    });
});
