import { __awaiter, __extends, __generator } from "tslib";
import Measure from './Measure';
import { Cartesian3, Color, Cartesian2 } from '@taotieh/cesium_extend';
var State;
(function (State) {
    State[State["READY"] = 0] = "READY";
    State[State["POINT_ORIGIN_SELECTED"] = 1] = "POINT_ORIGIN_SELECTED";
    State[State["OBJECT_SELECTED"] = 2] = "OBJECT_SELECTED";
    State[State["POINT_OBJECT_1_SELECTED"] = 3] = "POINT_OBJECT_1_SELECTED";
    State[State["POINT_OBJECT_2_SELECTED"] = 4] = "POINT_OBJECT_2_SELECTED";
    State[State["POINT_OBJECT_3_SELECTED"] = 5] = "POINT_OBJECT_3_SELECTED";
    State[State["DONE"] = 6] = "DONE";
})(State || (State = {}));
var MeasureDistancePointToSurface = /** @class */ (function (_super) {
    __extends(MeasureDistancePointToSurface, _super);
    function MeasureDistancePointToSurface(viewer, instance) {
        var _this = _super.call(this, viewer, instance) || this;
        _this._state = State.READY;
        _this._points = []; //[orign, obj_1, obj_2, obj_3]
        _this._vectors = []; //[v_1, v_2, normal]
        _this._toReset();
        return _this;
    }
    MeasureDistancePointToSurface.prototype._toSelectOrigin = function () {
        return __awaiter(this, void 0, void 0, function () {
            var _a, scene, origin;
            return __generator(this, function (_b) {
                switch (_b.label) {
                    case 0:
                        _a = this, scene = _a._viewer.scene, origin = _a._points[0];
                        return [4 /*yield*/, this._selectPoint(origin)];
                    case 1:
                        _b.sent();
                        console.log('选中原点, 下一步选则目标对象', origin);
                        this._state = State.POINT_ORIGIN_SELECTED;
                        this._drawPoint(origin, Color.RED, 6);
                        this.next();
                        return [2 /*return*/];
                }
            });
        });
    };
    MeasureDistancePointToSurface.prototype._toSelectObject = function () {
        return __awaiter(this, void 0, void 0, function () {
            var _a;
            return __generator(this, function (_b) {
                switch (_b.label) {
                    case 0:
                        _a = this;
                        return [4 /*yield*/, this._selectC3DTileFeature()];
                    case 1:
                        _a._feature = _b.sent();
                        this._state = State.OBJECT_SELECTED;
                        console.log('选中对象, 下一步选择目标平面上第一个点', this._feature);
                        this.next();
                        return [2 /*return*/];
                }
            });
        });
    };
    MeasureDistancePointToSurface.prototype._toSelectObjectPoint1 = function () {
        return __awaiter(this, void 0, void 0, function () {
            var _a, orign, obj_1;
            return __generator(this, function (_b) {
                switch (_b.label) {
                    case 0:
                        _a = this._points, orign = _a[0], obj_1 = _a[1];
                        return [4 /*yield*/, this._selectPoint(obj_1)];
                    case 1:
                        _b.sent();
                        this._state = State.POINT_OBJECT_1_SELECTED;
                        console.log('选中第一个点, 下一步选平面上另一点', obj_1);
                        this._drawPoint(obj_1, Color.GREEN, 4);
                        this.next();
                        return [2 /*return*/];
                }
            });
        });
    };
    MeasureDistancePointToSurface.prototype._toSelectObjectPoint2 = function () {
        return __awaiter(this, void 0, void 0, function () {
            var _a, orign, obj_1, obj_2;
            return __generator(this, function (_b) {
                switch (_b.label) {
                    case 0:
                        _a = this._points, orign = _a[0], obj_1 = _a[1], obj_2 = _a[2];
                        return [4 /*yield*/, this._selectPoint(obj_2)];
                    case 1:
                        _b.sent();
                        // TODO 判断 obj_2 的合法性, 不能与前一个点重合, 最好保持一定距离
                        this._state = State.POINT_OBJECT_2_SELECTED;
                        console.log('选中第二个点, 下一步选平面上最后一个点. ', [obj_1, obj_2]);
                        this._drawPoint(obj_2, Color.GREEN, 4);
                        this.next();
                        return [2 /*return*/];
                }
            });
        });
    };
    MeasureDistancePointToSurface.prototype._toSelectObjectPoint3 = function () {
        return __awaiter(this, void 0, void 0, function () {
            var _a, orign, obj_1, obj_2, obj_3;
            return __generator(this, function (_b) {
                switch (_b.label) {
                    case 0:
                        _a = this._points, orign = _a[0], obj_1 = _a[1], obj_2 = _a[2], obj_3 = _a[3];
                        return [4 /*yield*/, this._selectPoint(obj_3)];
                    case 1:
                        _b.sent();
                        // TODO 判断 obj_3 的合法性, 不能与前两点共线, 最好夹角足够大
                        this._state = State.POINT_OBJECT_3_SELECTED;
                        console.log('平面上三点, 准备就绪开始计算 ', [obj_1, obj_2, obj_3]);
                        this._drawPoint(obj_3, Color.GREEN, 4);
                        this.next();
                        return [2 /*return*/];
                }
            });
        });
    };
    MeasureDistancePointToSurface.prototype._toCalculateDistance = function () {
        return __awaiter(this, void 0, void 0, function () {
            var _a, _b, origin, obj_1, obj_2, obj_3, _c, v_1, v_2, normal, n_tmp, dist, drop;
            return __generator(this, function (_d) {
                _a = this, _b = _a._points, origin = _b[0], obj_1 = _b[1], obj_2 = _b[2], obj_3 = _b[3], _c = _a._vectors, v_1 = _c[0], v_2 = _c[1], normal = _c[2], n_tmp = _c[3];
                // 根据 obj_1, obj_2, obj_3 求法线
                Cartesian3.subtract(obj_2, obj_1, v_1);
                Cartesian3.subtract(obj_3, obj_1, v_2);
                // 根据 v_1, v_2 求平面法线
                Cartesian3.cross(v_1, v_2, normal);
                // 判断方向, 选择性的反转 normal, 使其始终是从 origin 指向 obj
                Cartesian3.subtract(obj_3, origin, n_tmp);
                if (Cartesian3.dot(n_tmp, normal) < 0) {
                    Cartesian3.negate(normal, normal);
                }
                Cartesian3.normalize(normal, normal);
                dist = Cartesian3.dot(n_tmp, normal);
                drop = Cartesian3.add(origin, Cartesian3.multiplyByScalar(normal, dist, n_tmp), obj_1);
                console.log('计算完毕, 开始绘图.', { origin: origin, normal: normal, drop: drop, dist: dist });
                this._toShowResult();
                this._state = State.DONE;
                this.next();
                return [2 /*return*/];
            });
        });
    };
    MeasureDistancePointToSurface.prototype._toShowResult = function () {
        var _a = this, _b = _a._points, origin = _b[0], drop = _b[1], middle = _b[2], _c = _a._vectors, v_1 = _c[0], v_2 = _c[1], normal = _c[2], n_tmp = _c[3];
        Cartesian3.add(origin, drop, middle);
        Cartesian3.multiplyByScalar(middle, 0.5, middle);
        var dist = Cartesian3.dot(n_tmp, normal);
        // 清除临时绘图
        this._clearEntity();
        // 绘制原点
        this._drawPoint(origin, Color.RED, 6);
        // 绘制垂足
        this._drawPoint(drop, Color.RED, 3);
        // 绘制激光线
        this._drawLine([origin, drop], Color.RED, 2);
        // 绘制标签
        this._drawLabel(middle, dist.toFixed(2) + " \u7C73", new Cartesian2(0, -9), new Color(0, 0, 0, 0.8));
    };
    MeasureDistancePointToSurface.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];
    };
    MeasureDistancePointToSurface.prototype._toReset = function () {
        var _a = this, ps = _a._points, vs = _a._vectors;
        vs[0] = Cartesian3.ZERO.clone();
        vs[1] = Cartesian3.ZERO.clone();
        vs[2] = Cartesian3.ZERO.clone();
        vs[3] = Cartesian3.ZERO.clone();
        ps[0] = Cartesian3.ZERO.clone();
        ps[1] = Cartesian3.ZERO.clone();
        ps[2] = Cartesian3.ZERO.clone();
        ps[3] = Cartesian3.ZERO.clone();
        this._toClearResult();
        this._state = State.READY;
    };
    MeasureDistancePointToSurface.prototype.start = function () {
        var _this = this;
        var cPo = this._instance.getInstancePointerControl();
        cPo.once('rightClick', function () { return _this.stop(); });
        this._toReset();
        console.log('开始测量');
        this.next();
    };
    MeasureDistancePointToSurface.prototype.next = function () {
        switch (this._state) {
            case State.READY:
                this._toSelectOrigin();
                break;
            case State.POINT_ORIGIN_SELECTED:
                this._toSelectObject();
                break;
            case State.OBJECT_SELECTED:
                this._toSelectObjectPoint1();
                break;
            case State.POINT_OBJECT_1_SELECTED:
                this._toSelectObjectPoint2();
                break;
            case State.POINT_OBJECT_2_SELECTED:
                this._toSelectObjectPoint3();
                break;
            case State.POINT_OBJECT_3_SELECTED:
                this._toCalculateDistance();
                break;
            case State.DONE:
                this._toShowResult();
                break;
            default:
                this._toReset();
        }
    };
    MeasureDistancePointToSurface.prototype.stop = function () { };
    return MeasureDistancePointToSurface;
}(Measure));
export default MeasureDistancePointToSurface;
