import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import { GoogleTms } from '@basemaps/geo';
import { Component, Fragment } from 'react';
import { Attributions } from '../attribution.js';
import { Config } from '../config.js';
import { ConfigData } from '../config.layer.js';
import { MapConfig } from '../config.map.js';
import { DebugMap } from '../debug.map.js';
import { WindowUrl } from '../url.js';
import { onMapLoaded } from './map.js';
function debugSlider(label, onInput) {
    return (_jsx("input", { className: "debug__slider", type: "range", min: "0", max: "1", step: "0.05", defaultValue: String(Config.map.debug[`debug.layer.${label}`]), onChange: onInput }));
}
export class Debug extends Component {
    constructor() {
        super(...arguments);
        this.debugMap = new DebugMap();
        this.state = {};
        this.waitForMap = () => {
            const map = this.props.map;
            if (map == null) {
                setTimeout(this.waitForMap, 20);
                return;
            }
            window.MaplibreMap = map;
            map.resize();
            onMapLoaded(map, () => {
                Config.map.on('change', () => {
                    if (this.props.map == null)
                        return;
                    const locationHash = WindowUrl.toHash(Config.map.getLocation(this.props.map));
                    const locationSearch = '?' + MapConfig.toUrl(Config.map);
                    window.history.replaceState(null, '', locationSearch + locationHash);
                    this.updateFromConfig();
                });
                this.updateFromConfig();
                if (Config.map.debug['debug.screenshot']) {
                    map.once('idle', async () => {
                        // Ensure all the attribution data has loaded
                        await Promise.all([...Attributions.values()]);
                        await new Promise((r) => setTimeout(r, 250));
                        // Jam a div into the page once the map has loaded so tools like playwright can see the map has finished loading
                        const loadedDiv = document.createElement('div');
                        loadedDiv.id = 'map-loaded';
                        loadedDiv.style.width = '1px';
                        loadedDiv.style.height = '1px';
                        document.body.appendChild(loadedDiv);
                    });
                }
            });
        };
        /** Show the source bounding box ont he map */
        this.toggleCogs = (e) => {
            const target = e.target;
            Config.map.setDebug('debug.cog', target.checked);
            this.setVectorShown(target.checked, 'cog');
        };
        /** Show the source bounding box ont he map */
        this.toggleSource = (e) => {
            const target = e.target;
            Config.map.setDebug('debug.source', target.checked);
            this.setVectorShown(target.checked, 'source');
        };
        this._loadingConfig = Promise.resolve();
        this.downloadSource = async () => {
            const im = this.state.imagery;
            if (im == null)
                return;
            const geoJson = ConfigData.getGeoJson(im);
            if (geoJson == null)
                return;
            // Create a magic a href to download the geojson
            const dataStr = `data:text/json;charset=utf-8,` + encodeURIComponent(JSON.stringify(geoJson));
            const aEl = document.createElement('a');
            aEl.setAttribute('href', dataStr);
            aEl.setAttribute('download', im.name + '.json');
            document.body.appendChild(aEl);
            aEl.click();
            aEl.remove();
        };
    }
    componentDidMount() {
        this.waitForMap();
    }
    updateFromConfig() {
        var _a;
        if (((_a = this.state.tileSet) === null || _a === void 0 ? void 0 : _a.id) !== Config.map.layerId || this.state.config !== Config.map.config) {
            this._loadingConfig = this._loadingConfig.then(() => this.loadConfig());
        }
        this.debugMap.setPurple(Config.map.debug['debug.background'] === 'magenta');
        this.debugMap.adjustRaster(this.props.map, 'osm', Config.map.debug['debug.layer.osm']);
        this.debugMap.adjustRaster(this.props.map, 'linz-aerial', Config.map.debug['debug.layer.linz-aerial']);
        this.debugMap.adjustVector(this.props.map, Config.map.debug['debug.layer.linz-topographic']);
        this.setVectorShown(Config.map.debug['debug.source'], 'source');
        this.setVectorShown(Config.map.debug['debug.cog'], 'cog');
    }
    async loadConfig() {
        var _a;
        const tileSetId = Config.map.layerId;
        if (((_a = this.state.tileSet) === null || _a === void 0 ? void 0 : _a.id) === tileSetId)
            return;
        return ConfigData.getTileSet(tileSetId).then((tileSet) => {
            this.setState({ tileSet, config: Config.map.config });
            if (tileSet == null)
                return;
            if (tileSet.layers.length !== 1)
                return;
            const projectionCode = Config.map.tileMatrix.projection.code;
            const imageryId = tileSet.layers[0][projectionCode];
            if (imageryId == null)
                return;
            this.debugMap.fetchSourceLayer(imageryId, 'cog').then((cog) => {
                this.setState({ isCog: cog != null });
            });
            return ConfigData.getImagery(tileSetId, imageryId).then((imagery) => {
                this.setState({ imagery, config: Config.map.config });
            });
        });
    }
    render() {
        var _a;
        if (Config.map.debug['debug.screenshot'])
            return null;
        const wmtsUrl = WindowUrl.toTileUrl("wmts" /* MapOptionType.Wmts */, Config.map.tileMatrix, Config.map.layerId, undefined, Config.map.config);
        const title = (_a = this.state.imagery) === null || _a === void 0 ? void 0 : _a.title;
        return (_jsxs("div", { className: "debug", children: [_jsxs("div", { className: "debug__info", children: [_jsx("label", { className: "debug__label", children: "Id" }), _jsx("div", { className: "debug__value", children: Config.map.layerId })] }), title == null ? null : (_jsxs("div", { className: "debug__info", children: [_jsx("label", { className: "debug__label", children: "Title" }), _jsx("div", { className: "debug__value", children: title })] })), _jsxs("div", { className: "debug__info", children: [_jsx("label", { className: "debug__label" }), _jsxs("div", { className: "debug__value", children: [Config.map.tileMatrix.projection.toEpsgString(), " - ", _jsx("a", { href: wmtsUrl, children: "WMTS" })] })] }), _jsxs("div", { className: "debug__info", children: [_jsx("label", { className: "debug__label", children: "TileMatrix" }), _jsx("div", { className: "debug__value", children: Config.map.tileMatrix.identifier })] }), this.renderSliders(), this.renderPurple(), this.renderCogToggle(), this.renderSourceToggle()] }));
    }
    renderPurple() {
        if (Config.map.debug['debug.screenshot'])
            return;
        return (_jsxs("div", { className: "debug__info", children: [_jsx("label", { className: "debug__label", children: "Purple" }), _jsx("input", { type: "checkbox", onChange: this.debugMap.togglePurple, checked: Config.map.debug['debug.background'] === 'magenta' })] }));
    }
    renderCogToggle() {
        if (this.state.imagery == null)
            return null;
        const cogLocation = WindowUrl.toImageryUrl(this.state.imagery.id, 'covering.geojson');
        if (!this.state.isCog)
            return;
        return (_jsxs(Fragment, { children: [_jsxs("div", { className: "debug__info", children: [_jsx("label", { className: "debug__label", children: _jsx("a", { href: cogLocation, title: "Source geojson", children: "Cogs" }) }), _jsx("input", { type: "checkbox", onChange: this.toggleCogs, checked: Config.map.debug['debug.cog'] })] }), this.state.featureCogId == null ? null : (_jsxs("div", { className: "debug__info", title: String(this.state.featureCogName), children: [_jsx("label", { className: "debug__label", children: "CogId" }), String(this.state.featureCogName).split('/').pop()] }))] }));
    }
    renderSourceToggle() {
        if (this.state.imagery == null)
            return null;
        return (_jsxs(Fragment, { children: [_jsxs("div", { className: "debug__info", children: [_jsx("label", { className: "debug__label", children: _jsx("a", { onClick: this.downloadSource, href: "#", title: "Source geojson", children: "Source" }) }), _jsx("input", { type: "checkbox", onChange: this.toggleSource, checked: Config.map.debug['debug.source'] })] }), this.state.featureSourceId == null ? null : (_jsxs("div", { className: "debug__info", title: String(this.state.featureSourceName), children: [_jsx("label", { className: "debug__label", children: "SourceId" }), String(this.state.featureSourceName).split('/').pop()] }))] }));
    }
    renderSliders() {
        // Disable the sliders for screenshots
        if (Config.map.debug['debug.screenshot'])
            return;
        // Only 3857 currently works with OSM/Topographic map
        if (Config.map.tileMatrix.identifier !== GoogleTms.identifier) {
            return (_jsxs("div", { className: "debug__info", children: [_jsx("label", { className: "debug__label", children: "LINZ Aerial" }), debugSlider('linz-aerial', this.debugMap.adjustLinzAerial)] }));
        }
        return (_jsxs(Fragment, { children: [_jsxs("div", { className: "debug__info", children: [_jsx("label", { className: "debug__label", children: "OSM" }), debugSlider('osm', this.debugMap.adjustOsm)] }), _jsxs("div", { className: "debug__info", children: [_jsx("label", { className: "debug__label", children: "Topographic" }), debugSlider('linz-topographic', this.debugMap.adjustTopographic)] }), _jsxs("div", { className: "debug__info", children: [_jsx("label", { className: "debug__label", children: "LINZ Aerial" }), debugSlider('linz-aerial', this.debugMap.adjustLinzAerial)] })] }));
    }
    trackMouseMove(layerId, type) {
        const sourceId = `${layerId}_${type}`;
        const layerFillId = `${sourceId}_fill`;
        const map = this.props.map;
        let lastFeatureId;
        const stateName = type === 'source' ? `featureSource` : `featureCog`;
        // Onclick copy the location into the clipboard
        map.on('click', layerFillId, (e) => {
            var _a, _b, _c;
            const features = e.features;
            if (features == null || features.length === 0)
                return;
            const firstFeature = features[0];
            const location = (_b = (_a = firstFeature.properties) === null || _a === void 0 ? void 0 : _a['location']) !== null && _b !== void 0 ? _b : (_c = firstFeature.properties) === null || _c === void 0 ? void 0 : _c['name'];
            if (location == null)
                return;
            navigator.clipboard.writeText(location).then(() => {
                const div = document.createElement('div');
                div.innerText = `Copied ${location}`;
                div.className = 'toast-message';
                div.title = location;
                document.body.appendChild(div);
                setTimeout(() => div.remove(), 2500);
            });
        });
        map.on('mousemove', layerFillId, (e) => {
            var _a;
            const features = e.features;
            if (features == null || features.length === 0)
                return;
            const firstFeature = features[0];
            if (firstFeature.id === lastFeatureId)
                return;
            if (lastFeatureId != null)
                map.setFeatureState({ source: sourceId, id: lastFeatureId }, { hover: false });
            lastFeatureId = firstFeature.id;
            this.setState({
                [`${stateName}Id`]: lastFeatureId,
                [`${stateName}Name`]: (_a = firstFeature.properties) === null || _a === void 0 ? void 0 : _a['name'],
            });
            map.setFeatureState({ source: sourceId, id: lastFeatureId }, { hover: true });
        });
        map.on('mouseleave', layerFillId, () => {
            if (lastFeatureId == null)
                return;
            map.setFeatureState({ source: sourceId, id: lastFeatureId }, { hover: false });
            lastFeatureId = undefined;
            this.setState({ [`${stateName}Id`]: undefined, [`${stateName}Name`]: undefined });
        });
    }
    setVectorShown(isShown, type) {
        const map = this.props.map;
        const layerId = Config.map.layerId;
        const sourceId = `${layerId}_${type}`;
        const layerFillId = `${sourceId}_fill`;
        const layerLineId = `${sourceId}_line`;
        if (isShown === false) {
            if (map.getLayer(layerFillId) == null)
                return;
            map.removeLayer(layerFillId);
            map.removeLayer(layerLineId);
            return;
        }
        if (map.getLayer(layerLineId) != null)
            return;
        const color = type === 'source' ? '#ff00ff' : '#ff0000';
        if (this.state.imagery == null)
            return;
        this.debugMap.loadSourceLayer(this.props.map, layerId, this.state.imagery, type).then(() => {
            if (map.getLayer(layerLineId) != null)
                return;
            // Fill is needed to make the mouse move work even though it has opacity 0
            map.addLayer({
                id: layerFillId,
                type: 'fill',
                source: sourceId,
                paint: {
                    'fill-opacity': ['case', ['boolean', ['feature-state', 'hover'], false], 0.25, 0],
                    'fill-color': color,
                },
            });
            this.trackMouseMove(layerId, type);
            map.addLayer({
                id: layerLineId,
                type: 'line',
                source: sourceId,
                paint: {
                    'line-color': color,
                    'line-opacity': ['case', ['boolean', ['feature-state', 'hover'], false], 1, 0.5],
                    'line-width': ['case', ['boolean', ['feature-state', 'hover'], false], 2, 1],
                },
            });
        });
    }
}
//# sourceMappingURL=debug.js.map