import { __awaiter, __extends, __generator } from "tslib";
import * as Cesium from '@msign/angularis';
import { throttle, debounce } from 'lodash';
import { TIMESPAN_INSTANT, TIMESPAN_SOON } from '../../core/Constant';
import Control from '../_Control';
import State from '../../core/State';
import PickMode from './Mods/Pick';
import FreeMode from './Mods/Free';
import FirstMode from './Mods/First';
import Instance from '../../core/Instance';
/** ******************************************
 *  鼠标(光标)行为的统一控制器
 *  所有鼠标行为均通过这个控制器进行注册和捕获
 *  不建议在其他地方单独注册 EventListener.
 *
 *******************************************/
var PointerControl = /** @class */ (function (_super) {
    __extends(PointerControl, _super);
    /**
     * @param domTracking 用于挂载鼠标事件监听的dom对象
     */
    function PointerControl(viewer) {
        var _this = _super.call(this) || this;
        _this._target = Cesium.Cartesian3.ZERO.clone();
        _this._isMultipleSelected = false;
        _this._selection = [];
        _this._selectionOriginMap = new WeakMap();
        _this._actionModeSupports = ['first', 'free', 'pan', 'orbit', 'pick'];
        _this._handlePointerDown = function (evt) {
            // console.log('PointerControl', '_handlePointerDown');
            _this.emit('down', evt);
            // 更新操作状态
            State.isOperating = true;
        };
        _this._handleTouchStart = function (evt) {
            // console.log('PointerControl', '_handlePointerDown');
            _this.emit('touchStart', evt);
            State.isOperating = true;
        };
        _this._handleTouchEnd = function (evt) {
            // console.log('PointerControl', '_handlePointerDown');
            _this.emit('up', evt);
            State.isOperating = false;
        };
        _this._handleTouchMove = function (evt) {
            // console.log('PointerControl', '_handlePointerDown');
            _this.emit('touchMove', evt);
        };
        _this._handlePointerMoveEnd = debounce(function () {
            _this.emit('moveEnd');
        }, TIMESPAN_SOON);
        _this._handlePointerMove = throttle(function (evt) {
            // console.log('PointerControl', '_handlePointerMove');
            _this.emit('move', evt);
            _this._handlePointerMoveEnd();
        }, TIMESPAN_INSTANT);
        _this._handlePointerUp = function (evt) { return __awaiter(_this, void 0, void 0, function () {
            return __generator(this, function (_a) {
                // console.log('PointerControl', '_handlePointerUp');
                this.emit('up', evt);
                State.isOperating = false;
                return [2 /*return*/];
            });
        }); };
        _this._handlePointerClick = function (evt) {
            // console.log('PointerControl', '_handlePointerClick');
            _this.emit('click', evt);
        };
        _this._handlePointerDbClick = function (evt) {
            // console.log('PointerControl', '_handlePointerDbClick');
            _this.emit('dbclick', evt);
        };
        _this._handlePointerEnter = function (evt) {
            // console.log('PointerControl', '_handlePointerEnter');
            _this.emit('enter', evt);
        };
        _this._handlePointerLeave = function (evt) {
            // console.log('PointerControl', '_handlePointerLeave');
            _this.emit('leave', evt);
        };
        _this._handleWheelEnd = debounce(function () {
            State.isOperating = false;
            _this.emit('wheelEnd');
            // console.log('wheel');
        }, TIMESPAN_SOON);
        _this._handleWheel = function (evt) {
            // console.log('PointerControl', '_handleWheel', evt);
            State.isOperating = true;
            _this.emit('wheel', evt);
            // console.log('wheel');
            // 该函数已内部防抖, 最后一次调用一秒后触发
            _this._handleWheelEnd();
        };
        _this._handleKeyDown = function (evt) {
            var key = evt.key;
            // console.log(`[${key}]按下`);
            switch (key) {
                case 'Control':
                    _this._isMultipleSelected = true;
                    break;
                default:
                    break;
            }
        };
        _this._handleKeyUp = function (evt) {
            var key = evt.key;
            // console.log(`[${key}]抬起`);
            switch (key) {
                case 'Control':
                    _this._isMultipleSelected = false;
                    break;
                default:
                    break;
            }
        };
        _this._viewer = viewer;
        _this._scene = viewer.scene;
        _this._camera = viewer.camera;
        _this._domTracking = viewer.container;
        _this._modPick = new PickMode(_this, viewer);
        _this._modFree = new FreeMode(_this, viewer);
        _this._modFirst = new FirstMode(_this, viewer);
        _this._bindModsEvent();
        _this._uninstallEvents();
        _this._installEvents();
        _this._installEventsTransfer([_this._modPick]);
        _this.actionMode = 'free';
        return _this;
    }
    PointerControl.prototype._installTouchStartEvent = function () {
        var _a = this, _domTracking = _a._domTracking, _handleTouchStart = _a._handleTouchStart;
        _domTracking.addEventListener('touchstart', _handleTouchStart);
    };
    PointerControl.prototype._installTouchEndEvent = function () {
        var _a = this, _domTracking = _a._domTracking, _handleTouchEnd = _a._handleTouchEnd;
        _domTracking.addEventListener('touchend', _handleTouchEnd);
    };
    PointerControl.prototype._installTouchMoveEvent = function () {
        var _a = this, _domTracking = _a._domTracking, _handleTouchMove = _a._handleTouchMove;
        _domTracking.addEventListener('touchmove', _handleTouchMove);
    };
    PointerControl.prototype._installPointerDownEvent = function () {
        var _a = this, _domTracking = _a._domTracking, _handlePointerDown = _a._handlePointerDown;
        _domTracking.addEventListener('pointerdown', _handlePointerDown);
    };
    PointerControl.prototype._installPointerUpEvent = function () {
        var _a = this, _domTracking = _a._domTracking, _handlePointerUp = _a._handlePointerUp;
        _domTracking.addEventListener('pointerup', _handlePointerUp);
    };
    PointerControl.prototype._installPointerMoveEvent = function () {
        var _a = this, _domTracking = _a._domTracking, _handlePointerMove = _a._handlePointerMove;
        _domTracking.addEventListener('pointermove', _handlePointerMove);
    };
    PointerControl.prototype._installPointerClickEvent = function () {
        var _a = this, _domTracking = _a._domTracking, _handlePointerClick = _a._handlePointerClick;
        _domTracking.addEventListener('click', _handlePointerClick);
    };
    PointerControl.prototype._installPointerDbClickEvent = function () {
        var _a = this, _domTracking = _a._domTracking, _handlePointerDbClick = _a._handlePointerDbClick;
        _domTracking.addEventListener('dblclick', _handlePointerDbClick);
    };
    PointerControl.prototype._installPointerEnterEvent = function () {
        var _a = this, _domTracking = _a._domTracking, _handlePointerEnter = _a._handlePointerEnter;
        _domTracking.addEventListener('pointerenter', _handlePointerEnter);
    };
    PointerControl.prototype._installPointerLeaveEvent = function () {
        var _a = this, _domTracking = _a._domTracking, _handlePointerLeave = _a._handlePointerLeave;
        _domTracking.addEventListener('pointerleave', _handlePointerLeave);
    };
    PointerControl.prototype._installWheelEvent = function () {
        var _a = this, _domTracking = _a._domTracking, _handleWheel = _a._handleWheel;
        _domTracking.addEventListener('wheel', _handleWheel);
    };
    PointerControl.prototype._installKeyEvent = function () {
        document.addEventListener('keydown', this._handleKeyDown);
        document.addEventListener('keyup', this._handleKeyUp);
    };
    PointerControl.prototype._uninstallTouchStartEvent = function () {
        var _a = this, _domTracking = _a._domTracking, _handleTouchStart = _a._handleTouchStart;
        _domTracking.removeEventListener('touchstart', _handleTouchStart);
    };
    PointerControl.prototype._uninstallTouchEndEvent = function () {
        var _a = this, _domTracking = _a._domTracking, _handleTouchEnd = _a._handleTouchEnd;
        _domTracking.removeEventListener('touchend', _handleTouchEnd);
    };
    PointerControl.prototype._uninstallTouchMoveEvent = function () {
        var _a = this, _domTracking = _a._domTracking, _handleTouchMove = _a._handleTouchMove;
        _domTracking.removeEventListener('touchmove', _handleTouchMove);
    };
    PointerControl.prototype._uninstallPointerDownEvent = function () {
        var _a = this, _domTracking = _a._domTracking, _handlePointerDown = _a._handlePointerDown;
        _domTracking.removeEventListener('pointerdown', _handlePointerDown);
    };
    PointerControl.prototype._uninstallPointerUpEvent = function () {
        var _a = this, _domTracking = _a._domTracking, _handlePointerUp = _a._handlePointerUp;
        _domTracking.removeEventListener('pointerup', _handlePointerUp);
    };
    PointerControl.prototype._uninstallPointerMoveEvent = function () {
        var _a = this, _domTracking = _a._domTracking, _handlePointerMove = _a._handlePointerMove;
        _domTracking.removeEventListener('pointemove', _handlePointerMove);
    };
    PointerControl.prototype._uninstallPointerClickEvent = function () {
        var _a = this, _domTracking = _a._domTracking, _handlePointerClick = _a._handlePointerClick;
        _domTracking.removeEventListener('click', _handlePointerClick);
    };
    PointerControl.prototype._uninstallPointerDbClickEvent = function () {
        var _a = this, _domTracking = _a._domTracking, _handlePointerDbClick = _a._handlePointerDbClick;
        _domTracking.removeEventListener('dblclick', _handlePointerDbClick);
    };
    PointerControl.prototype._uninstallPointerEnterEvent = function () {
        var _a = this, _domTracking = _a._domTracking, _handlePointerEnter = _a._handlePointerEnter;
        _domTracking.removeEventListener('pointerenter', _handlePointerEnter);
    };
    PointerControl.prototype._uninstallPointerLeaveEvent = function () {
        var _a = this, _domTracking = _a._domTracking, _handlePointerLeave = _a._handlePointerLeave;
        _domTracking.removeEventListener('pointerleave', _handlePointerLeave);
    };
    PointerControl.prototype._uninstallWheelEvent = function () {
        var _a = this, _domTracking = _a._domTracking, _handleWheel = _a._handleWheel;
        _domTracking.removeEventListener('wheel', _handleWheel);
    };
    PointerControl.prototype._uninstallKeyEvent = function () {
        document.removeEventListener('keydown', this._handleKeyDown);
        document.removeEventListener('keyup', this._handleKeyUp);
    };
    PointerControl.prototype._installEvents = function () {
        this._installPointerClickEvent();
        this._installPointerDbClickEvent();
        this._installPointerDownEvent();
        this._installPointerEnterEvent();
        this._installPointerLeaveEvent();
        this._installPointerMoveEvent();
        this._installPointerUpEvent();
        this._installWheelEvent();
        this._installTouchStartEvent();
        this._installTouchEndEvent();
        this._installTouchMoveEvent();
        this._installKeyEvent();
        // 屏蔽浏览器自带右键菜单
        // const dom = this._viewer.container;
        // dom.addEventListener(
        //   'contextmenu',
        //   evt => {
        //     evt.stopPropagation();
        //     evt.returnValue = false;
        //     evt.cancelBubble = true;
        //     this.emit('rightClick', evt);
        //     return false;
        //   },
        //   true
        // );
    };
    PointerControl.prototype._uninstallEvents = function () {
        this._uninstallPointerClickEvent();
        this._uninstallPointerDbClickEvent();
        this._uninstallPointerDownEvent();
        this._uninstallPointerEnterEvent();
        this._uninstallPointerLeaveEvent();
        this._uninstallPointerMoveEvent();
        this._uninstallPointerUpEvent();
        this._installWheelEvent();
        this._uninstallTouchStartEvent();
        this._uninstallTouchEndEvent();
        this._uninstallTouchMoveEvent();
        this._uninstallKeyEvent();
    };
    PointerControl.prototype._installEventsTransfer = function (handlers) {
        var _this = this;
        var _loop_1 = function (iHdl) {
            var hdl = handlers[iHdl];
            hdl.eventNames().forEach(function (evtName) {
                hdl.on(evtName, function (evt) {
                    _this.emit(evtName, evt);
                });
            });
        };
        for (var iHdl = 0; iHdl < handlers.length; iHdl++) {
            _loop_1(iHdl);
        }
    };
    PointerControl.prototype._bindModsEvent = function () {
        var _this = this;
        var modFree = this._modFree;
        /** *****************************************
         *  绑定模式内的事件
         ********************************************/
        modFree.on('pick', function (obj) {
            // 选中对象
            // console.log('选中对象', obj);
            var propsNames = [];
            if (obj.id instanceof Cesium.Entity) {
                _this.emit('pickMarker', obj.id._id);
                _this.emit('pickEntity', obj.id._id);
                return;
            }
            obj.getPropertyNames(propsNames);
            var props = {};
            propsNames.forEach(function (name) {
                props[name] = obj.getProperty(name);
            });
            // console.log('选中对象', props);
            // 加入选择集
            // console.log(obj);
            // todo
            _this.emit('pick', props);
        });
        modFree.on('rightClick', function (data) {
            var feature = data.feature;
            var props = {};
            if (feature && feature.getPropertyNames) {
                var propsNames = [];
                feature.getPropertyNames(propsNames);
                propsNames.forEach(function (name) {
                    props[name] = feature.getProperty(name);
                });
                data.feat = props;
                _this.selectionAppend(feature, _this._isMultipleSelected);
            }
            _this.emit('rightClick', data);
        });
        modFree.on('picknone', function () {
            // 选中虚空
            // console.log('选中虚空');
            // 清空选择集
            _this.selectionClear();
            _this.emit('picknone');
        });
        modFree.on('hover', function (feat) {
            // 悬停对象
            // console.log('悬停对象', feat);
        });
        modFree.on('unhover', function (feat) {
            // 悬停丢失
            // console.log('悬停丢失', feat);
        });
    };
    PointerControl.prototype.selectionClear = function () {
        var _a = this, selection = _a._selection, oMap = _a._selectionOriginMap;
        selection.forEach(function (feature) {
            var color = oMap.get(feature).color;
            feature.color = color;
            oMap.delete(feature);
        });
        selection.length = 0;
    };
    PointerControl.prototype.selectionRemove = function (feature) {
        return __awaiter(this, void 0, void 0, function () {
            var _a, selection, oMap, ix, om, color;
            return __generator(this, function (_b) {
                _a = this, selection = _a._selection, oMap = _a._selectionOriginMap;
                ix = selection.indexOf(feature);
                om = oMap.get(feature);
                if (om) {
                    color = om.color;
                    feature.color = color;
                    oMap.delete(feature);
                }
                ix > -1 && selection.splice(ix, 1);
                return [2 /*return*/];
            });
        });
    };
    PointerControl.prototype.selectionAppend = function (feature, isMutipled) {
        if (isMutipled === void 0) { isMutipled = false; }
        return __awaiter(this, void 0, void 0, function () {
            var _a, selection, oMap, cSc;
            return __generator(this, function (_b) {
                switch (_b.label) {
                    case 0:
                        _a = this, selection = _a._selection, oMap = _a._selectionOriginMap;
                        this.selectionRemove(feature);
                        if (!isMutipled) {
                            this.selectionClear();
                        }
                        oMap.set(feature, {
                            color: feature.color.clone()
                        });
                        feature.color = Cesium.Color.YELLOW.withAlpha(1);
                        selection.push(feature);
                        return [4 /*yield*/, Instance.getInstanceSceneControl()];
                    case 1:
                        cSc = _b.sent();
                        return [4 /*yield*/, cSc.forceRender(50)];
                    case 2:
                        _b.sent();
                        return [2 /*return*/];
                }
            });
        });
    };
    Object.defineProperty(PointerControl.prototype, "target", {
        get: function () {
            return this._target;
        },
        set: function (val) {
            if (val == this._target)
                return;
            this._target = val;
            // this._modPan.target = val;
            // this._modOrbit.target = val;
            // this._modRod.target = val;
        },
        enumerable: true,
        configurable: true
    });
    Object.defineProperty(PointerControl.prototype, "actionMode", {
        get: function () {
            return this._actionMode;
        },
        set: function (val) {
            var _this = this;
            if (val === this._actionMode) {
                return;
            }
            var _a = this, modes = _a._actionModeSupports, modPick = _a._modPick, modFree = _a._modFree, modFirst = _a._modFirst;
            if (modes.indexOf(val) === -1) {
                return;
            }
            switch (val) {
                case 'first':
                    modFree.isActive = false;
                    modPick.isActive = false;
                    modFirst.isActive = true;
                    modFirst.once('exit', function () {
                        // 用户可能会使用键盘 esc 键退出第一人称模式
                        // 故而需要捕捉退出事件, 切换回自由浏览模式
                        _this.actionMode = 'free';
                    });
                    break;
                case 'free':
                    modFirst.isActive = false;
                    modPick.isActive = false;
                    modFree.isActive = true;
                    break;
                case 'orbit':
                    break;
                case 'pick':
                    modFirst.isActive = false;
                    modFree.isActive = false;
                    modPick.isActive = true;
                    break;
                case 'dragmove':
                case 'dragrota':
                    /** ************************************
                     *  场景编辑模式下可开启的特殊模式
                     *  此模式下可交互式拖拽场景中的元素
                     *  改变陈设
                     ***************************************/
                    break;
                default:
            }
            this._actionMode = val;
        },
        enumerable: true,
        configurable: true
    });
    return PointerControl;
}(Control));
export default PointerControl;
