var __extends = (this && this.__extends) || (function () {
    var extendStatics = function (d, b) {
        extendStatics = Object.setPrototypeOf ||
            ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
            function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
        return extendStatics(d, b);
    };
    return function (d, b) {
        if (typeof b !== "function" && b !== null)
            throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
        extendStatics(d, b);
        function __() { this.constructor = d; }
        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
    };
})();
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
var __generator = (this && this.__generator) || function (thisArg, body) {
    var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
    return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
    function verb(n) { return function (v) { return step([n, v]); }; }
    function step(op) {
        if (f) throw new TypeError("Generator is already executing.");
        while (g && (g = 0, op[0] && (_ = 0)), _) try {
            if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
            if (y = 0, t) op = [op[0] & 2, t.value];
            switch (op[0]) {
                case 0: case 1: t = op; break;
                case 4: _.label++; return { value: op[1], done: false };
                case 5: _.label++; y = op[1]; op = [0]; continue;
                case 7: op = _.ops.pop(); _.trys.pop(); continue;
                default:
                    if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
                    if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
                    if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
                    if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
                    if (t[2]) _.ops.pop();
                    _.trys.pop(); continue;
            }
            op = body.call(thisArg, _);
        } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
        if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
    }
};
import { AcDbLine, AcGiLineWeight } from '@mlightcad/data-model';
import { AcEdCommand, AcEdCorsorType, AcEdOpenMode, AcEdPreviewJig, AcEdPromptPointOptions, AcEdPromptStatus, AcEdViewMode } from '../editor';
import { AcApI18n } from '../i18n';
import { makeBadge, makeDot, makeLiveBadge, measurementColor } from '../util';
import { registerMeasurementCleanup } from './AcApClearMeasurementsCmd';
/** Returns the 2D Euclidean distance between two world points. */
function calcDist(p1, p2) {
    var dx = p2.x - p1.x;
    var dy = p2.y - p1.y;
    return Math.sqrt(dx * dx + dy * dy);
}
/**
 * Preview jig for the distance measurement command.
 *
 * Renders a live rubber-band line from the fixed first point to the current
 * cursor position. The badge showing the live distance is rendered by the
 * jig itself and is removed when the jig ends — it is intentionally short-lived
 * and intrinsic to the interactive input UX.
 */
var AcApMeasureDistanceJig = /** @class */ (function (_super) {
    __extends(AcApMeasureDistanceJig, _super);
    function AcApMeasureDistanceJig(view, p1, color) {
        var _this = _super.call(this, view) || this;
        _this._p1 = p1;
        _this._view = view;
        _this._line = new AcDbLine(p1, p1);
        _this._line.color = color;
        _this._line.lineWeight = AcGiLineWeight.LineWeight070;
        // Live badge — short-lived, cleaned up in end()
        _this._badge = makeLiveBadge(color);
        return _this;
    }
    Object.defineProperty(AcApMeasureDistanceJig.prototype, "entity", {
        get: function () {
            return this._line;
        },
        enumerable: false,
        configurable: true
    });
    AcApMeasureDistanceJig.prototype.update = function (p2) {
        this._line.endPoint = p2;
        var dist = calcDist(this._p1, p2);
        if (dist < 0.0001) {
            this._badge.style.display = 'none';
            return;
        }
        this._badge.textContent = "~ ".concat(dist.toFixed(3), " m");
        this._badge.style.display = 'block';
        var mid = { x: (this._p1.x + p2.x) / 2, y: (this._p1.y + p2.y) / 2 };
        var rect = this._view.canvas.getBoundingClientRect();
        var s = this._view.worldToScreen(mid);
        this._badge.style.left = "".concat(s.x + rect.left, "px");
        this._badge.style.top = "".concat(s.y + rect.top, "px");
    };
    AcApMeasureDistanceJig.prototype.end = function () {
        _super.prototype.end.call(this);
        this._badge.remove();
    };
    return AcApMeasureDistanceJig;
}(AcEdPreviewJig));
export { AcApMeasureDistanceJig };
/**
 * Command that measures the straight-line distance between two points.
 *
 * Prompts the user to pick two world points, then registers a transient CAD
 * line between them. Persistent DOM overlays (dots + badge) are placed via
 * {@link AcTrHtmlTransientManager} using CSS2DObject, so they track zoom/pan
 * automatically without manual viewChanged listeners.
 */
var AcApMeasureDistanceCmd = /** @class */ (function (_super) {
    __extends(AcApMeasureDistanceCmd, _super);
    function AcApMeasureDistanceCmd() {
        var _this = _super.call(this) || this;
        _this.mode = AcEdOpenMode.Read;
        return _this;
    }
    AcApMeasureDistanceCmd.prototype.execute = function (context) {
        return __awaiter(this, void 0, void 0, function () {
            var editor, color;
            var _this = this;
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0:
                        editor = context.view.editor;
                        color = measurementColor(context.doc.database);
                        return [4 /*yield*/, context.view.withMode(AcEdViewMode.SELECTION, function () {
                                return editor.withCursor(AcEdCorsorType.Crosshair, function () { return __awaiter(_this, void 0, void 0, function () {
                                    var p1Prompt, p1Result, p1, p2Prompt, p2Result, p2, dist, line, htManager, id, mid;
                                    return __generator(this, function (_a) {
                                        switch (_a.label) {
                                            case 0:
                                                p1Prompt = new AcEdPromptPointOptions(AcApI18n.t('jig.measureDistance.firstPoint'));
                                                return [4 /*yield*/, editor.getPoint(p1Prompt)];
                                            case 1:
                                                p1Result = _a.sent();
                                                if (p1Result.status !== AcEdPromptStatus.OK)
                                                    return [2 /*return*/];
                                                p1 = p1Result.value;
                                                p2Prompt = new AcEdPromptPointOptions(AcApI18n.t('jig.measureDistance.secondPoint'));
                                                p2Prompt.useBasePoint = true;
                                                p2Prompt.jig = new AcApMeasureDistanceJig(context.view, p1, color);
                                                return [4 /*yield*/, editor.getPoint(p2Prompt)];
                                            case 2:
                                                p2Result = _a.sent();
                                                if (p2Result.status !== AcEdPromptStatus.OK)
                                                    return [2 /*return*/];
                                                p2 = p2Result.value;
                                                dist = calcDist(p1, p2);
                                                line = new AcDbLine(p1, p2);
                                                line.color = color;
                                                line.lineWeight = AcGiLineWeight.LineWeight070;
                                                context.view.addTransientEntity(line);
                                                htManager = context.view.htmlTransientManager;
                                                id = "dist-".concat(Date.now());
                                                mid = { x: (p1.x + p2.x) / 2, y: (p1.y + p2.y) / 2 };
                                                htManager.add("".concat(id, "-dot1"), makeDot(color), p1, 'measurement');
                                                htManager.add("".concat(id, "-dot2"), makeDot(color), p2, 'measurement');
                                                htManager.add("".concat(id, "-badge"), makeBadge(color, "~ ".concat(dist.toFixed(3), " m")), mid, 'measurement');
                                                registerMeasurementCleanup(function () {
                                                    context.view.removeTransientEntity(line.objectId);
                                                    htManager.remove("".concat(id, "-dot1"));
                                                    htManager.remove("".concat(id, "-dot2"));
                                                    htManager.remove("".concat(id, "-badge"));
                                                });
                                                return [2 /*return*/];
                                        }
                                    });
                                }); });
                            })];
                    case 1:
                        _a.sent();
                        return [2 /*return*/];
                }
            });
        });
    };
    return AcApMeasureDistanceCmd;
}(AcEdCommand));
export { AcApMeasureDistanceCmd };
//# sourceMappingURL=AcApMeasureDistanceCmd.js.map