import { __awaiter, __extends, __generator } from "tslib";
import { throttle } from "lodash";
import { Cartesian3, Color, CallbackProperty, Cartesian2, } from "@taotieh/cesium_extend";
import Measure from "./Measure";
// import Instance from '../../../core/Instance';
import { TIMESPAN_INSTANT } from "../../../core/Constant";
var State;
(function (State) {
    State[State["READY"] = 0] = "READY";
    State[State["POINT_ORIGIN_SELECTED"] = 1] = "POINT_ORIGIN_SELECTED";
    State[State["POINT_LATEST_SELECTED"] = 2] = "POINT_LATEST_SELECTED";
    State[State["DONE"] = 3] = "DONE";
})(State || (State = {}));
var MeasureDistancePointChain = /** @class */ (function (_super) {
    __extends(MeasureDistancePointChain, _super);
    function MeasureDistancePointChain(viewer, instance) {
        var _this = _super.call(this, viewer, instance) || this;
        _this._state = State.READY;
        _this._points = []; //[orign, ..., latest]
        _this._vectors = []; //[v_1, ...]
        _this._tracingEnts = [];
        /** **********************************************************
         *  这里用 Protected 是有原因的. 具体看基类 Measure.
         *  因为基类也实现了 _onMove 的基础功能. 这里实际是在重写属性.
         *************************************************************/
        _this._onMove = throttle(function (evt) { return __awaiter(_this, void 0, void 0, function () {
            var _a, target, points, ents, cPo, latest;
            return __generator(this, function (_b) {
                switch (_b.label) {
                    case 0:
                        _a = this, target = _a._target, points = _a._points, ents = _a._tracingEnts;
                        return [4 /*yield*/, this._instance.getInstancePointerControl()];
                    case 1:
                        cPo = _b.sent();
                        cPo.target.clone(target);
                        latest = points[points.length - 1];
                        if (!latest || Cartesian3.equals(target, Cartesian3.ZERO))
                            return [2 /*return*/];
                        // while (ents.length) {
                        //   const ent = ents.pop();
                        //   ent && this._rmEnt(ent);
                        // }
                        // ents.push(this._drawLine([latest, target], Color.GREEN, 1));
                        this._latest = latest;
                        return [2 /*return*/];
                }
            });
        }); }, TIMESPAN_INSTANT);
        _this._onPointerDown = function (evt) { return __awaiter(_this, void 0, void 0, function () {
            var button;
            return __generator(this, function (_a) {
                button = evt.button;
                // console.log('_onPointerDown', evt);
                if (button === 2) {
                    // 右键结束
                    this.stop();
                }
                return [2 /*return*/];
            });
        }); };
        _this._toReset();
        return _this;
    }
    MeasureDistancePointChain.prototype._getMoveLinePoints = function () {
        var _this = this;
        return function () {
            var _a = _this, _target = _a._target, _latest = _a._latest;
            if (!_latest || Cartesian3.equals(_target, Cartesian3.ZERO))
                return [];
            return [_target, _latest];
        };
    };
    MeasureDistancePointChain.prototype._getMoveLineMiddle = function () {
        var _this = this;
        return function () {
            var _a = _this, _target = _a._target, _latest = _a._latest;
            var middle = Cartesian3.ZERO.clone();
            if (!_latest || Cartesian3.equals(_target, Cartesian3.ZERO))
                return middle;
            Cartesian3.add(_target, _latest, middle);
            Cartesian3.multiplyByScalar(middle, 0.5, middle);
            return middle;
        };
    };
    MeasureDistancePointChain.prototype._getMoveLineLabel = function () {
        var _this = this;
        return function () {
            var _a = _this, _target = _a._target, _latest = _a._latest;
            if (!_latest || Cartesian3.equals(_target, Cartesian3.ZERO))
                return "";
            var dist = Cartesian3.distance(_target, _latest);
            return dist.toFixed(2) + " \u7C73";
        };
    };
    MeasureDistancePointChain.prototype._toSelectOrigin = function () {
        return __awaiter(this, void 0, void 0, function () {
            var _a, scene, points, origin;
            return __generator(this, function (_b) {
                switch (_b.label) {
                    case 0:
                        _a = this, scene = _a._viewer.scene, points = _a._points;
                        return [4 /*yield*/, this._selectPoint(new Cartesian3())];
                    case 1:
                        origin = _b.sent();
                        if (this._state === State.DONE) {
                            return [2 /*return*/];
                        }
                        points.push(origin);
                        console.log("选中原点, 下一步选则目标对象", origin);
                        this.emit("message", "选中原点, 下一步萱蕚目标对象", origin);
                        this._state = State.POINT_ORIGIN_SELECTED;
                        /* 添加实时跟踪线条 */
                        this._moveline = this._drawLine(new CallbackProperty(this._getMoveLinePoints(), false), Color.YELLOW.withAlpha(0.3), 2);
                        this._movelineLabel = this._drawLabel(new CallbackProperty(this._getMoveLineMiddle(), false), new CallbackProperty(this._getMoveLineLabel(), false));
                        this._drawPoint(origin, Color.RED, 6);
                        this.next();
                        return [2 /*return*/];
                }
            });
        });
    };
    MeasureDistancePointChain.prototype._toSelectLatest = function () {
        return __awaiter(this, void 0, void 0, function () {
            var _a, scene, points, latest, _b, p1, p2, middle, dist;
            return __generator(this, function (_c) {
                switch (_c.label) {
                    case 0:
                        _a = this, scene = _a._viewer.scene, points = _a._points;
                        return [4 /*yield*/, this._selectPoint(new Cartesian3())];
                    case 1:
                        latest = _c.sent();
                        /* 完成后，鼠标up事件会继续执行，这里做判断避免无限循环 */
                        if (this._state === State.DONE) {
                            return [2 /*return*/];
                        }
                        points.push(latest);
                        console.log("选中一个新点, 右键结束选择", latest);
                        this.emit("message", "选中一个新点, 右键结束选择", latest);
                        this._state = State.POINT_LATEST_SELECTED;
                        _b = points.slice(points.length - 2), p1 = _b[0], p2 = _b[1];
                        middle = Cartesian3.ZERO.clone();
                        dist = Cartesian3.distance(p1, p2);
                        this._drawPoint(latest, Color.YELLOW, 6);
                        this._drawLine(points.slice(points.length - 2), Color.YELLOW, 2);
                        Cartesian3.add(p1, p2, middle);
                        Cartesian3.multiplyByScalar(middle, 0.5, middle);
                        this._drawLabel(middle, dist.toFixed(2) + " \u7C73", new Cartesian2(0, -9), new Color(0, 0, 0, 0.8));
                        this.next();
                        return [2 /*return*/];
                }
            });
        });
    };
    MeasureDistancePointChain.prototype._toCalculateDistance = function () {
        return __awaiter(this, void 0, void 0, function () {
            var _a, ps, vs;
            return __generator(this, function (_b) {
                _a = this, ps = _a._points, vs = _a._vectors;
                console.log("计算完毕, 开始绘图.", { origin: origin });
                this._toShowResult();
                this._state = State.DONE;
                this.next();
                return [2 /*return*/];
            });
        });
    };
    MeasureDistancePointChain.prototype._doneMeasure = function () {
        this._state = State.DONE;
        this.next();
    };
    MeasureDistancePointChain.prototype._toShowResult = function () { };
    MeasureDistancePointChain.prototype._toClearResult = function () {
        var _a = this, _b = _a._points, origin = _b[0], drop = _b[1], _c = _a._vectors, v_1 = _c[0], v_2 = _c[1], normal = _c[2], n_tmp = _c[3];
    };
    MeasureDistancePointChain.prototype._toReset = function () {
        var _a = this, ps = _a._points, vs = _a._vectors;
        ps.length = 0;
        vs.length = 0;
        this._toClearResult();
        this._state = State.READY;
    };
    MeasureDistancePointChain.prototype._installSubEvents = function () {
        return __awaiter(this, void 0, void 0, function () { return __generator(this, function (_a) {
            return [2 /*return*/];
        }); });
    };
    MeasureDistancePointChain.prototype._uninstallSubEvents = function () {
        return __awaiter(this, void 0, void 0, function () {
            var cPo;
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0: return [4 /*yield*/, this._instance.getInstancePointerControl()];
                    case 1:
                        cPo = _a.sent();
                        cPo.off("move", this._onMove);
                        return [2 /*return*/];
                }
            });
        });
    };
    MeasureDistancePointChain.prototype.start = function () {
        return __awaiter(this, void 0, void 0, function () {
            var cPo;
            var _this = this;
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0:
                        cPo = this._instance.getInstancePointerControl();
                        cPo.once('rightClick', function () { return _this.stop(); });
                        _super.prototype.start.call(this);
                        this._toReset();
                        return [4 /*yield*/, this._installSubEvents()];
                    case 1:
                        _a.sent();
                        console.log("开始测量");
                        this.next();
                        return [2 /*return*/];
                }
            });
        });
    };
    MeasureDistancePointChain.prototype.next = function () {
        return __awaiter(this, void 0, void 0, function () {
            var _a;
            return __generator(this, function (_b) {
                switch (_b.label) {
                    case 0:
                        _a = this._state;
                        switch (_a) {
                            case State.READY: return [3 /*break*/, 1];
                            case State.POINT_ORIGIN_SELECTED: return [3 /*break*/, 3];
                            case State.POINT_LATEST_SELECTED: return [3 /*break*/, 5];
                            case State.DONE: return [3 /*break*/, 7];
                        }
                        return [3 /*break*/, 9];
                    case 1: return [4 /*yield*/, this._toSelectOrigin()];
                    case 2:
                        _b.sent();
                        return [3 /*break*/, 11];
                    case 3: return [4 /*yield*/, this._toSelectLatest()];
                    case 4:
                        _b.sent();
                        return [3 /*break*/, 11];
                    case 5: return [4 /*yield*/, this._toSelectLatest()];
                    case 6:
                        _b.sent();
                        return [3 /*break*/, 11];
                    case 7: return [4 /*yield*/, this._toShowResult()];
                    case 8:
                        _b.sent();
                        this.emit("message", "完成测量");
                        return [3 /*break*/, 11];
                    case 9: return [4 /*yield*/, this._toReset()];
                    case 10:
                        _b.sent();
                        _b.label = 11;
                    case 11: return [2 /*return*/];
                }
            });
        });
    };
    MeasureDistancePointChain.prototype.stop = function () {
        return __awaiter(this, void 0, void 0, function () {
            var _a;
            return __generator(this, function (_b) {
                switch (_b.label) {
                    case 0:
                        _a = this._state;
                        switch (_a) {
                            case State.READY: return [3 /*break*/, 1];
                            case State.POINT_ORIGIN_SELECTED: return [3 /*break*/, 2];
                            case State.POINT_LATEST_SELECTED: return [3 /*break*/, 3];
                            case State.DONE: return [3 /*break*/, 5];
                        }
                        return [3 /*break*/, 6];
                    case 1:
                        this.emit("message", "取消测量");
                        this._doneMeasure();
                        return [3 /*break*/, 8];
                    case 2:
                        this.emit("message", "仅选择了起点, 终止测量");
                        this._doneMeasure();
                        return [3 /*break*/, 8];
                    case 3: return [4 /*yield*/, this._toCalculateDistance()];
                    case 4:
                        _b.sent();
                        return [3 /*break*/, 8];
                    case 5:
                        this.emit("message", "已经完成测量");
                        this._doneMeasure();
                        return [3 /*break*/, 8];
                    case 6: return [4 /*yield*/, this._toReset()];
                    case 7:
                        _b.sent();
                        _b.label = 8;
                    case 8:
                        this._moveline && this._clearEntity(this._moveline);
                        this._movelineLabel && this._clearEntity(this._movelineLabel);
                        _super.prototype.stop.call(this);
                        return [4 /*yield*/, this._uninstallSubEvents()];
                    case 9:
                        _b.sent();
                        return [2 /*return*/];
                }
            });
        });
    };
    return MeasureDistancePointChain;
}(Measure));
export default MeasureDistancePointChain;
