import { __awaiter, __extends, __generator } from "tslib";
import { TIMESPAN_INSTANT } from '../core/Constant';
import { Cesium3DTileset, Entity, Color, WebMercatorTilingScheme, UrlTemplateImageryProvider, EllipsoidTerrainProvider, Cesium3DTileStyle, ClassificationType, SingleTileImageryProvider, VerticalOrigin, LabelStyle, Cartesian2, 
// Batched3DModel3DTileContent,
Cartesian3, Cartographic, 
// @ts-ignore
Cesium3DTileColorBlendMode, 
// @ts-ignore
IonResource, createWorldTerrain, ArcGisMapServerImageryProvider } from '@taotieh/cesium_extend';
import { tiles } from './Assets';
import Control from './_Control';
var img_sat_google_wgs84 = tiles.img_sat_google_wgs84, trr_world = tiles.trr_world;
var SceneControl = /** @class */ (function (_super) {
    __extends(SceneControl, _super);
    function SceneControl(instance, viewer) {
        var _this = _super.call(this, instance) || this;
        _this._pCache = new Map();
        _this._layerOblique = [];
        _this._layerStyleConf = {
            highLightIds: [],
            hideIds: [],
            opacity: 1,
            opacityCover: false,
            colors: {},
            onlyShowIds: []
        };
        // 载入数据栈
        _this._layerStack = [];
        // 选择集
        _this._selection = [];
        _this._hoverOriginColor = Color.WHITE.clone();
        _this._viewer = viewer;
        _this._scene = viewer.scene;
        (function () { return __awaiter(_this, void 0, void 0, function () {
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0: return [4 /*yield*/, Promise.all([this._imageOff(), this._terrainOff()])];
                    case 1:
                        _a.sent();
                        return [4 /*yield*/, Promise.all([this._imageOn(), this._terrainOn()])];
                    case 2:
                        _a.sent();
                        return [4 /*yield*/, this._resetCamera()];
                    case 3:
                        _a.sent();
                        return [2 /*return*/];
                }
            });
        }); })();
        return _this;
    }
    SceneControl.prototype._layer3DTileClassificationHelperSwitch = function (isActive) {
        if (isActive === void 0) { isActive = true; }
        // const
        if (isActive) {
            var l3DC = this._layer3DTileClassification;
        }
    };
    SceneControl.prototype._resetCamera = function () {
        return __awaiter(this, void 0, void 0, function () {
            var c, camera;
            return __generator(this, function (_a) {
                c = JSON.parse("{\"position\":{\"x\":-4249578,\"y\":9391230,\"z\":2394244},\"direction\":{\"x\":0.47,\"y\":-0.87,\"z\":0.123},\"up\":{\"x\":0.1,\"y\":0.2,\"z\":1}}");
                camera = this._scene.camera;
                camera.flyTo({
                    destination: c.position,
                    orientation: {
                        direction: c.direction,
                        up: c.up,
                    },
                });
                return [2 /*return*/];
            });
        });
    };
    // 地形, 地球, 影像相关
    SceneControl.prototype._earthOn = function () {
        return __awaiter(this, void 0, void 0, function () {
            var scene;
            return __generator(this, function (_a) {
                scene = this._viewer.scene;
                // scene.globe = new Globe();
                scene.globe.show = true;
                return [2 /*return*/];
            });
        });
    };
    SceneControl.prototype._earthOff = function () {
        return __awaiter(this, void 0, void 0, function () {
            var scene;
            return __generator(this, function (_a) {
                scene = this._viewer.scene;
                // await this._imageOff();
                // await this._terrainOff();
                // await this._globalDepthTestOff();
                // scene.globe = null as any;
                scene.globe.show = false;
                return [2 /*return*/];
            });
        });
    };
    SceneControl.prototype._imageOn = function (urlTpl, _a) {
        if (urlTpl === void 0) { urlTpl = img_sat_google_wgs84; }
        var _b = _a === void 0 ? {} : _a, _c = _b.tilingScheme, tilingScheme = _c === void 0 ? new WebMercatorTilingScheme() : _c, _d = _b.maximumLevel, maximumLevel = _d === void 0 ? 21 : _d;
        return __awaiter(this, void 0, void 0, function () {
            var _e, viewer, pC, ly;
            return __generator(this, function (_f) {
                _e = this, viewer = _e._viewer, pC = _e._pCache;
                ly = pC.get(urlTpl);
                if (ly) {
                    viewer.imageryLayers.contains(ly) ||
                        viewer.imageryLayers.addImageryProvider(ly);
                }
                else {
                    ly = viewer.imageryLayers.addImageryProvider(new UrlTemplateImageryProvider({
                        url: urlTpl,
                        credit: '',
                        tilingScheme: tilingScheme,
                        maximumLevel: maximumLevel,
                    }));
                    pC.set(urlTpl, ly);
                }
                return [2 /*return*/];
            });
        });
    };
    SceneControl.prototype._imageOff = function (urlTpl) {
        return __awaiter(this, void 0, void 0, function () {
            var _a, viewer, pC, ly;
            return __generator(this, function (_b) {
                _a = this, viewer = _a._viewer, pC = _a._pCache;
                if (urlTpl) {
                    ly = pC.get(urlTpl);
                    if (!ly)
                        return [2 /*return*/];
                    viewer.imageryLayers.contains(ly) && viewer.imageryLayers.remove(ly);
                    pC.delete(urlTpl);
                }
                else {
                    viewer.imageryLayers.removeAll();
                    pC.clear();
                }
                return [2 /*return*/];
            });
        });
    };
    SceneControl.prototype._terrainOn = function (urlTpl, option) {
        if (urlTpl === void 0) { urlTpl = trr_world; }
        if (option === void 0) { option = {
            requestWaterMask: true,
            requestVertexNormals: true,
        }; }
        return __awaiter(this, void 0, void 0, function () {
            var _a, viewer, pC;
            return __generator(this, function (_b) {
                _a = this, viewer = _a._viewer, pC = _a._pCache;
                viewer.terrainProvider = createWorldTerrain();
                return [2 /*return*/];
            });
        });
    };
    SceneControl.prototype._terrainOff = function () {
        return __awaiter(this, void 0, void 0, function () {
            var viewer;
            return __generator(this, function (_a) {
                viewer = this._viewer;
                viewer.terrainProvider = new EllipsoidTerrainProvider();
                return [2 /*return*/];
            });
        });
    };
    SceneControl.prototype._globalDepthTestOn = function () {
        return __awaiter(this, void 0, void 0, function () {
            var viewer;
            return __generator(this, function (_a) {
                viewer = this._viewer;
                viewer.scene.globe && (viewer.scene.globe.depthTestAgainstTerrain = true);
                return [2 /*return*/];
            });
        });
    };
    SceneControl.prototype._globalDepthTestOff = function () {
        return __awaiter(this, void 0, void 0, function () {
            var viewer;
            return __generator(this, function (_a) {
                viewer = this._viewer;
                viewer.scene.globe && (viewer.scene.globe.depthTestAgainstTerrain = false);
                return [2 /*return*/];
            });
        });
    };
    SceneControl.prototype.zoomToTile = function () {
        return __awaiter(this, void 0, void 0, function () {
            var viewer;
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0:
                        viewer = this._viewer;
                        // @ts-ignore
                        return [4 /*yield*/, viewer.zoomTo(this._layer3DTile)];
                    case 1:
                        // @ts-ignore
                        _a.sent();
                        // @ts-ignore
                        setTimeout(function () { return viewer._postRender(); }, 200);
                        return [2 /*return*/];
                }
            });
        });
    };
    SceneControl.prototype.destroy3DTile = function (tileset) {
        return __awaiter(this, void 0, void 0, function () {
            var viewer, scene;
            return __generator(this, function (_a) {
                viewer = this._viewer;
                scene = viewer.scene;
                tileset && scene.primitives.remove(tileset);
                return [2 /*return*/];
            });
        });
    };
    SceneControl.prototype.loadLayer3DTile = function (url, _a) {
        var clear = _a.clear, _b = _a.initStyle, initStyle = _b === void 0 ? false : _b, _c = _a.isOblique, isOblique = _c === void 0 ? false : _c, _d = _a.autoFocus, autoFocus = _d === void 0 ? true : _d, _e = _a.testId, testId = _e === void 0 ? 0 : _e;
        return __awaiter(this, void 0, void 0, function () {
            var layer3DTile, viewer, scene, cSta, state;
            var _this = this;
            return __generator(this, function (_f) {
                switch (_f.label) {
                    case 0:
                        clear && this.destroy3DTile(this._layer3DTile);
                        layer3DTile = new Cesium3DTileset({
                            url: testId ? IonResource.fromAssetId(testId) : url,
                            maximumScreenSpaceError: 16,
                            maximumNumberOfLoadedTiles: 1024,
                            pointCloudShading: {
                                attenuation: true,
                                maximumAttenuation: 2,
                                geometricErrorScale: 2,
                            },
                            preferLeaves: true,
                            backFaceCulling: false,
                            skipLevelOfDetail: true,
                            dynamicScreenSpaceError: true,
                            maximumMemoryUsage: 2048
                        });
                        viewer = this._viewer;
                        scene = viewer.scene;
                        scene.primitives.add(layer3DTile);
                        cSta = this._instance.getInstanceStateControl();
                        state = cSta.state;
                        //设置颜色模式为替换Cesium3DTileStyle
                        layer3DTile['colorBlendMode'] = Cesium3DTileColorBlendMode.REPLACE;
                        return [4 /*yield*/, layer3DTile['readyPromise']];
                    case 1:
                        _f.sent();
                        if (initStyle) {
                            this._layer3DTile = layer3DTile;
                            window['layer3DTile'] = layer3DTile;
                            this.doAssembleStyle();
                        }
                        if (isOblique) {
                            this._layerOblique && this._layerOblique.push(layer3DTile);
                        }
                        console.log('layer3DTile ready.');
                        setTimeout(function () {
                            autoFocus && _this.zoomToTile();
                        }, 0);
                        window['viewer'] = viewer;
                        return [2 /*return*/, layer3DTile];
                }
            });
        });
    };
    SceneControl.prototype.loadLayerPointCloud = function (url, clear) {
        if (clear === void 0) { clear = false; }
        return __awaiter(this, void 0, void 0, function () {
            var layerPointCloud, viewer, scene;
            return __generator(this, function (_a) {
                layerPointCloud = new Cesium3DTileset({
                    url: url,
                    pointCloudShading: {
                        attenuation: true,
                        maximumAttenuation: 2,
                        geometricErrorScale: 2,
                    },
                });
                layerPointCloud.style = new Cesium3DTileStyle({
                    pointSize: '5.0',
                });
                viewer = this._viewer;
                scene = viewer.scene;
                if (clear)
                    scene['_primitives'].removeAll();
                scene.primitives.add(layerPointCloud);
                window['layerPointCloud'] = layerPointCloud;
                // @ts-ignore
                viewer.zoomTo(layerPointCloud);
                this._layer3DTile = layerPointCloud;
                layerPointCloud['skipStyleSet'] = true;
                return [2 /*return*/, layerPointCloud];
            });
        });
    };
    SceneControl.prototype.loadClassificationTile = function (tileset) {
        var scene = this._viewer.scene;
        var layer3DTileClassification = (this._layer3DTileClassification = new Cesium3DTileset({
            url: tileset,
            maximumScreenSpaceError: 16,
            maximumNumberOfLoadedTiles: 1024,
            classificationType: ClassificationType.CESIUM_3D_TILE,
        }));
        scene.primitives.add(layer3DTileClassification);
        // todo debug only
        window['layer3DTileClassification'] = layer3DTileClassification;
        return layer3DTileClassification;
    };
    SceneControl.prototype.unloadLayer = function (layer) {
        return __awaiter(this, void 0, void 0, function () {
            var viewer, scene;
            return __generator(this, function (_a) {
                viewer = this._viewer;
                scene = viewer.scene;
                return [2 /*return*/, scene.primitives.contains(layer) && scene.primitives.remove(layer)];
            });
        });
    };
    Object.defineProperty(SceneControl.prototype, "isEarthVisible", {
        get: function () {
            return this._scene.globe && true;
        },
        set: function (val) {
            if (val) {
                this._earthOn();
            }
            else {
                this._earthOff();
            }
        },
        enumerable: true,
        configurable: true
    });
    SceneControl.prototype.doAssembleStyle = function () {
        var _layer3DTile = this._layer3DTile;
        if (!_layer3DTile || _layer3DTile['skipStyleSet'])
            return;
        var _layerStyleConf = this._layerStyleConf;
        var colorOption = {
            // evaluateColor: function(feature, result) {
            //   return Color.clone(Color.YELLOW, result);
            // }
            conditions: [
                // ['${color}', '${color}'],
                // ['true', 'color("${color}")'],
                [
                    'true',
                    !_layerStyleConf['opacityCover']
                        ? 'rgba(${red}, ${green}, ${blue},' +
                            _layerStyleConf['opacity'] +
                            ')'
                        : 'rgba(64,64,128,' + _layerStyleConf['opacity'] + ')',
                ],
            ],
        };
        // 组装颜色设置条件
        // @ts-ignore
        var colors = _layerStyleConf.colors, hideIds = _layerStyleConf.hideIds, highLightIds = _layerStyleConf.highLightIds, onlyShowIds = _layerStyleConf.onlyShowIds;
        for (var key in colors) {
            // @ts-ignore
            colorOption.conditions.unshift([
                "regExp('_' + String(${id}) + '_').test('_" +
                    colors[key].ids.join('_') +
                    "_')",
                key,
            ]);
        }
        // 组装高亮清单
        highLightIds.length
            ? colorOption.conditions.unshift([
                "regExp('_' + String(${id}) + '_').test('_" +
                    highLightIds.join('_') +
                    "_')",
                'rgba(223,193,26,1)',
            ])
            : '';
        // 组装隐藏对象条件
        hideIds.length
            ? colorOption.conditions.unshift([
                "regExp('_' + String(${id}) + '_').test('_" +
                    hideIds.join('_') +
                    "_')",
                'rgba(1,1,1,0)',
            ])
            : '';
        console.log('colorOption', colorOption);
        // @ts-ignore
        _layer3DTile.style = new Cesium3DTileStyle({
            color: colorOption,
            show: onlyShowIds.length ? "regExp('_' + String(${id}) + '_').test('_" + onlyShowIds.join('_') + "_')" : 'true',
            meta: {
                description: '"Building DbId ${id}"',
            },
        });
        this.forceRender(100);
    };
    SceneControl.prototype.doSetOnlyVisibleStyle = function (ids) {
        if (!ids || !(ids instanceof Array))
            return;
        this._layerStyleConf['onlyShowIds'] = ids;
        this.doAssembleStyle();
    };
    SceneControl.prototype.doSetColorBlendMode = function (tile, type) {
        switch (type) {
            case 'HIGHLIGHT':
                tile.colorBlendMode = Cesium3DTileColorBlendMode.HIGHLIGHT;
                break;
            case 'MIX':
                tile.colorBlendMode = Cesium3DTileColorBlendMode.MIX;
                break;
            case 'REPLACE':
                tile.colorBlendMode = Cesium3DTileColorBlendMode.REPLACE;
                break;
        }
    };
    SceneControl.prototype.doSetColorStyle = function (ids, color) {
        var _a;
        var colors = this._layerStyleConf['colors'];
        colors[color]
            ? (_a = colors[color].ids).push.apply(_a, ids) : (colors[color] = { ids: ids });
        this.doAssembleStyle();
    };
    SceneControl.prototype.doSetColorStyleSingle = function (id, color) {
        var colors = this._layerStyleConf['colors'];
        if (colors[color]) {
            !colors[color].ids.includes(id) && colors[color].ids.push(id);
        }
        else {
            colors[color] = { ids: [id] };
        }
    };
    SceneControl.prototype.doClearColorStyle = function () {
        this._layerStyleConf['colors'] = {};
        this.doAssembleStyle();
    };
    SceneControl.prototype.doClearVisibleStyle = function () {
        this._layerStyleConf['hideIds'] = [];
        this.doAssembleStyle();
    };
    SceneControl.prototype.doSetVisibleStyle = function (ids, isSHow) {
        // @ts-ignore
        var hideIds = this._layerStyleConf.hideIds;
        ids.forEach(function (id) {
            if (isSHow) {
                hideIds.includes(id) ? hideIds.splice(hideIds.indexOf(id), 1) : '';
            }
            else {
                !hideIds.includes(id) ? hideIds.push(id) : '';
            }
        });
        this.doAssembleStyle();
    };
    SceneControl.prototype.doSetHighLightStyle = function (ids) {
        this._layerStyleConf['highLightIds'] = ids;
        this.doAssembleStyle();
    };
    SceneControl.prototype.doSetOpacityStyle = function (opacity, cover) {
        if (cover === void 0) { cover = false; }
        var _layerStyleConf = this._layerStyleConf;
        _layerStyleConf['opacity'] = opacity;
        _layerStyleConf['opacityCover'] = cover;
        this.doAssembleStyle();
    };
    SceneControl.prototype.resetCamera = function () {
        var _a = this, viewer = _a._viewer, lyStack = _a._layerStack;
        var camera = viewer.camera, scene = viewer.scene;
        if (lyStack.length) {
            var tar = lyStack[lyStack.length - 1];
        }
    };
    SceneControl.prototype.doSetObliqueVisible = function (flag) {
        var layerOblique = this._layerOblique;
        layerOblique && layerOblique.forEach(function (item) {
            item.show = flag;
        });
    };
    SceneControl.prototype.doSetArcGisMapImagerLayer = function (url) {
        return __awaiter(this, void 0, void 0, function () {
            var _viewer, imgProvider, imagery;
            return __generator(this, function (_a) {
                _viewer = this._viewer;
                imgProvider = new ArcGisMapServerImageryProvider({
                    url: url,
                });
                imagery = _viewer.imageryLayers.addImageryProvider(imgProvider);
                imagery.alpha = 1.0;
                return [2 /*return*/];
            });
        });
    };
    SceneControl.prototype.doSetImagerLayer = function (url) {
        return __awaiter(this, void 0, void 0, function () {
            var _viewer, imgProvider, imagery;
            return __generator(this, function (_a) {
                _viewer = this._viewer;
                imgProvider = new SingleTileImageryProvider({
                    url: url,
                });
                imagery = _viewer.imageryLayers.addImageryProvider(imgProvider);
                imagery.alpha = 1.0;
                return [2 /*return*/];
            });
        });
    };
    SceneControl.prototype.addLocationMarker = function (option) {
        console.log(option, 'addLocationMarker');
        var _viewer = this._viewer;
        var label = option.label, position = option.position, image = option.image, id = option.id, car3 = option.car3, width = option.width, height = option.height;
        var location = {};
        if (car3) {
            location = position;
        }
        else {
            location = Cartesian3.fromDegrees(Number(position.long) || 0, Number(position.lat) || 0, position.elevation || 2000);
        }
        var entityOption = {
            position: location,
            id: id,
            billboard: {
                disableDepthTestDistance: Number.POSITIVE_INFINITY,
                image: image || require('../assets/img/location.png'),
                width: width || 64,
                height: height || 64,
            },
            label: {
                text: label || '',
                font: '14pt monospace',
                style: LabelStyle.FILL_AND_OUTLINE,
                outlineWidth: 2,
                verticalOrigin: VerticalOrigin.TOP,
                pixelOffset: new Cartesian2(0, -64),
            },
        };
        // @ts-ignore
        return _viewer.entities.add(entityOption);
    };
    SceneControl.prototype.removeById = function (id) {
        var _viewer = this._viewer;
        _viewer.entities.removeById(id);
    };
    SceneControl.prototype.pickPosition = function (_a) {
        var x = _a.x, y = _a.y;
        var target = Cartesian3.ZERO.clone();
        var targetGraph = Cartographic.ZERO.clone();
        var scene = this.viewer.scene;
        var cart2 = new Cartesian2(x, y);
        scene.pickPosition(cart2, target);
        // @ts-ignore
        Cartographic.fromCartesian(target, scene.globe.ellipsoid, targetGraph);
        if (targetGraph.height < 1) {
            return;
        }
        var obj;
        try {
            obj = scene.pick(cart2);
        }
        catch (e) {
            return;
        }
        if (obj.id instanceof Entity) {
            return;
        }
        var propsNames = [];
        obj.getPropertyNames(propsNames);
        var props = {};
        propsNames.forEach(function (name) {
            props[name] = obj.getProperty(name);
        });
        if (props.id) {
            this.doSetHighLightStyle([props.id]);
        }
    };
    /** *****************************************
     *  强制刷新, 持续一定时间
     ********************************************/
    SceneControl.prototype.forceRender = function (timespan) {
        if (timespan === void 0) { timespan = TIMESPAN_INSTANT; }
        return __awaiter(this, void 0, void 0, function () {
            var viewer, scene;
            var _this = this;
            return __generator(this, function (_a) {
                viewer = this._viewer;
                scene = viewer.scene;
                if (!scene.requestRenderMode)
                    return [2 /*return*/, this];
                return [2 /*return*/, new Promise(function (resolve) {
                        scene.requestRenderMode = false;
                        setTimeout(function () {
                            scene.requestRenderMode = true;
                            resolve(_this);
                        }, timespan);
                    })];
            });
        });
    };
    Object.defineProperty(SceneControl.prototype, "scene", {
        get: function () {
            return this._scene;
        },
        enumerable: true,
        configurable: true
    });
    Object.defineProperty(SceneControl.prototype, "viewer", {
        get: function () {
            return this._viewer;
        },
        enumerable: true,
        configurable: true
    });
    SceneControl.prototype.terrainOff = function () {
        return this._terrainOff();
    };
    SceneControl.prototype.terrainOn = function () {
        return this._terrainOn();
    };
    SceneControl.prototype.imageOff = function () {
        return this._imageOff();
    };
    SceneControl.prototype.imageOn = function () {
        return this._imageOn();
    };
    Object.defineProperty(SceneControl.prototype, "styleConf", {
        get: function () {
            return this._layerStyleConf;
        },
        set: function (val) {
            val && (this._layerStyleConf = val);
            this.doAssembleStyle();
        },
        enumerable: true,
        configurable: true
    });
    return SceneControl;
}(Control));
export default SceneControl;
