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 { AcDbPolyline, AcGePoint2d, AcGePoint3d } from '@mlightcad/data-model';
import { AcApDocManager } from '../app';
import { AcEdCommand, AcEdOpenMode, AcEdPreviewJig, AcEdPromptAngleOptions, AcEdPromptDoubleOptions, AcEdPromptPointOptions, AcEdPromptStateMachine, AcEdPromptStatus, eventBus } from '../editor';
import { AcApI18n } from '../i18n';
var EPSILON = 1e-9;
var FILLET_BULGE_BASE = Math.tan(Math.PI / 8);
var DEFAULT_RECT_SETTINGS = {
    chamferDist1: 0,
    chamferDist2: 0,
    filletRadius: 0,
    width: 0,
    elevation: 0,
    thickness: 0,
    rotation: 0
};
function addKeyword(prompt, key) {
    prompt.keywords.add(AcApI18n.t("jig.rect.keywords.".concat(key, ".display")), AcApI18n.t("jig.rect.keywords.".concat(key, ".global")), AcApI18n.t("jig.rect.keywords.".concat(key, ".local")));
}
function addDoubleKeyword(prompt, key) {
    prompt.keywords.add(AcApI18n.t("jig.rect.keywords.".concat(key, ".display")), AcApI18n.t("jig.rect.keywords.".concat(key, ".global")), AcApI18n.t("jig.rect.keywords.".concat(key, ".local")));
}
function warnRectMessage(key) {
    eventBus.emit('message', {
        message: AcApI18n.t("jig.rect.".concat(key)),
        type: 'warning'
    });
}
function toWorldPoint(origin, local, rotation) {
    var cos = Math.cos(rotation);
    var sin = Math.sin(rotation);
    return new AcGePoint2d(origin.x + local.x * cos - local.y * sin, origin.y + local.x * sin + local.y * cos);
}
function toLocalVector(origin, point, rotation) {
    var dx = point.x - origin.x;
    var dy = point.y - origin.y;
    var cos = Math.cos(rotation);
    var sin = Math.sin(rotation);
    return new AcGePoint2d(dx * cos + dy * sin, -dx * sin + dy * cos);
}
function normalizeNonNegative(value) {
    if (!Number.isFinite(value !== null && value !== void 0 ? value : NaN))
        return 0;
    return Math.max(0, value !== null && value !== void 0 ? value : 0);
}
function buildSquareVertices(lx, ly) {
    return [
        { point: new AcGePoint2d(0, 0) },
        { point: new AcGePoint2d(lx, 0) },
        { point: new AcGePoint2d(lx, ly) },
        { point: new AcGePoint2d(0, ly) }
    ];
}
function buildChamferVertices(lx, ly, distance1, distance2) {
    var sx = lx >= 0 ? 1 : -1;
    var sy = ly >= 0 ? 1 : -1;
    var absX = Math.abs(lx);
    var absY = Math.abs(ly);
    var d1 = Math.min(normalizeNonNegative(distance1), absX / 2);
    var d2 = Math.min(normalizeNonNegative(distance2), absY / 2);
    if (d1 <= EPSILON && d2 <= EPSILON) {
        return buildSquareVertices(lx, ly);
    }
    var c1Out = new AcGePoint2d(sx * d1, 0);
    var c1In = new AcGePoint2d(0, sy * d2);
    var c2In = new AcGePoint2d(lx - sx * d1, 0);
    var c2Out = new AcGePoint2d(lx, sy * d2);
    var c3In = new AcGePoint2d(lx, ly - sy * d2);
    var c3Out = new AcGePoint2d(lx - sx * d1, ly);
    var c4In = new AcGePoint2d(sx * d1, ly);
    var c4Out = new AcGePoint2d(0, ly - sy * d2);
    return [
        { point: c1Out },
        { point: c2In },
        { point: c2Out },
        { point: c3In },
        { point: c3Out },
        { point: c4In },
        { point: c4Out },
        { point: c1In }
    ];
}
function buildFilletVertices(lx, ly, radius) {
    var absX = Math.abs(lx);
    var absY = Math.abs(ly);
    var r = Math.min(normalizeNonNegative(radius), absX / 2, absY / 2);
    if (r <= EPSILON)
        return buildSquareVertices(lx, ly);
    var chamferLike = buildChamferVertices(lx, ly, r, r);
    var orientation = lx * ly >= 0 ? 1 : -1;
    var bulge = orientation * FILLET_BULGE_BASE;
    // Arc segments are: c2In->c2Out, c3In->c3Out, c4In->c4Out, c1In->c1Out(closed).
    // These are represented by bulge on vertices 1, 3, 5, 7 respectively.
    return chamferLike.map(function (vertex, index) { return ({
        point: vertex.point,
        bulge: index % 2 === 1 ? bulge : undefined
    }); });
}
function resolveRectVertices(lx, ly, settings) {
    if (settings.filletRadius > EPSILON) {
        return buildFilletVertices(lx, ly, settings.filletRadius);
    }
    if (settings.chamferDist1 > EPSILON || settings.chamferDist2 > EPSILON) {
        return buildChamferVertices(lx, ly, settings.chamferDist1, settings.chamferDist2);
    }
    return buildSquareVertices(lx, ly);
}
function updateRect(rect, firstPoint, input, settings) {
    var lx = 0;
    var ly = 0;
    if (input.mode === 'corner') {
        var local = toLocalVector(firstPoint, input.secondPoint, settings.rotation);
        lx = local.x;
        ly = local.y;
    }
    else {
        lx = input.length;
        ly = input.width;
    }
    if (Math.abs(lx) <= EPSILON || Math.abs(ly) <= EPSILON)
        return false;
    rect.reset(false);
    var vertices = resolveRectVertices(lx, ly, settings);
    var segWidth = normalizeNonNegative(settings.width);
    vertices.forEach(function (vertex, index) {
        var worldPoint = toWorldPoint(firstPoint, vertex.point, settings.rotation);
        if (segWidth > EPSILON) {
            rect.addVertexAt(index, worldPoint, vertex.bulge, segWidth, segWidth);
        }
        else {
            rect.addVertexAt(index, worldPoint, vertex.bulge);
        }
    });
    rect.elevation = settings.elevation;
    rect.closed = true;
    return true;
}
/**
 * Dynamic preview jig for RECT command.
 */
var AcApRectJig = /** @class */ (function (_super) {
    __extends(AcApRectJig, _super);
    /**
     * Creates a dynamic rectangle preview jig.
     *
     * @param view - Active editor view used to render transient geometry.
     * @param start - First corner point of the rectangle.
     * @param settingsProvider - Callback that returns current command settings.
     */
    function AcApRectJig(view, start, settingsProvider) {
        var _this = _super.call(this, view) || this;
        _this._rect = new AcDbPolyline();
        _this._firstPoint = new AcGePoint2d(start);
        _this._settingsProvider = settingsProvider;
        return _this;
    }
    Object.defineProperty(AcApRectJig.prototype, "entity", {
        /**
         * Gets the transient polyline entity displayed by the jig.
         */
        get: function () {
            return this._rect;
        },
        enumerable: false,
        configurable: true
    });
    /**
     * Rebuilds preview geometry from the current cursor point.
     *
     * @param secondPoint - Dynamic opposite corner point under the cursor.
     */
    AcApRectJig.prototype.update = function (secondPoint) {
        updateRect(this._rect, this._firstPoint, { mode: 'corner', secondPoint: secondPoint }, this._settingsProvider());
    };
    return AcApRectJig;
}(AcEdPreviewJig));
export { AcApRectJig };
/**
 * Static rectangle preview jig used for non-point prompts (angle/number input).
 *
 * The geometry is built once in the constructor and then kept unchanged.
 *
 * @typeParam T - Prompt value type that drives this jig instance.
 */
var AcApRectStaticJig = /** @class */ (function (_super) {
    __extends(AcApRectStaticJig, _super);
    /**
     * Creates a static preview jig with precomputed rectangle geometry.
     *
     * @param view - Active editor view.
     * @param firstPoint - Rectangle base corner.
     * @param input - Rectangle construction input (corner or dimensions).
     * @param settings - Rectangle style/transform settings.
     */
    function AcApRectStaticJig(view, firstPoint, input, settings) {
        var _this = _super.call(this, view) || this;
        _this._rect = new AcDbPolyline();
        updateRect(_this._rect, firstPoint, input, settings);
        return _this;
    }
    Object.defineProperty(AcApRectStaticJig.prototype, "entity", {
        /**
         * Gets the transient static rectangle entity.
         */
        get: function () {
            return this._rect;
        },
        enumerable: false,
        configurable: true
    });
    /**
     * No-op update hook required by preview jig interface.
     *
     * @param _value - Prompt value (unused for static preview).
     */
    AcApRectStaticJig.prototype.update = function (_value) {
        // No-op. Static preview.
    };
    return AcApRectStaticJig;
}(AcEdPreviewJig));
function cloneRectSettings(settings) {
    return {
        chamferDist1: settings.chamferDist1,
        chamferDist2: settings.chamferDist2,
        filletRadius: settings.filletRadius,
        width: settings.width,
        elevation: settings.elevation,
        thickness: settings.thickness,
        rotation: settings.rotation
    };
}
function isPositive(value) {
    return Number.isFinite(value !== null && value !== void 0 ? value : NaN) && (value !== null && value !== void 0 ? value : 0) > EPSILON;
}
/**
 * Command to create one rectangle with AutoCAD-like branching options.
 */
var AcApRectCmd = /** @class */ (function (_super) {
    __extends(AcApRectCmd, _super);
    /**
     * Creates RECT command instance.
     */
    function AcApRectCmd() {
        var _this = _super.call(this) || this;
        _this.mode = AcEdOpenMode.Write;
        return _this;
    }
    /**
     * Command entry point.
     *
     * Flow:
     * 1. Prompt first corner and first-stage options.
     * 2. Prompt second-corner input, dimensions, or area workflow.
     * 3. Build final polyline and append it to model space.
     *
     * @param context - Current application/document context.
     */
    AcApRectCmd.prototype.execute = function (context) {
        return __awaiter(this, void 0, void 0, function () {
            var settings, firstPoint, secondInput, rect, isValid;
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0:
                        settings = cloneRectSettings(AcApRectCmd._settings);
                        return [4 /*yield*/, this.promptFirstCorner(settings)];
                    case 1:
                        firstPoint = _a.sent();
                        if (!firstPoint)
                            return [2 /*return*/];
                        return [4 /*yield*/, this.promptSecondInput(context, firstPoint, settings)];
                    case 2:
                        secondInput = _a.sent();
                        if (!secondInput)
                            return [2 /*return*/];
                        rect = new AcDbPolyline();
                        isValid = updateRect(rect, firstPoint, secondInput, settings);
                        if (!isValid) {
                            warnRectMessage('invalidRect');
                            return [2 /*return*/];
                        }
                        if (settings.thickness > EPSILON) {
                            warnRectMessage('thicknessNotSupported');
                        }
                        context.doc.database.tables.blockTable.modelSpace.appendEntity(rect);
                        AcApRectCmd._settings = cloneRectSettings(settings);
                        return [2 /*return*/];
                }
            });
        });
    };
    /**
     * Prompts for the first rectangle corner while handling setup keywords.
     *
     * Supported options at this step: Chamfer, Elevation, Fillet, Thickness, Width.
     *
     * @param settings - Mutable settings object updated in-place by options.
     * @returns First corner point, or `undefined` when user cancels.
     */
    AcApRectCmd.prototype.promptFirstCorner = function (settings) {
        return __awaiter(this, void 0, void 0, function () {
            var prompt_1, result, keyword, ok, ok, ok, ok, ok;
            var _a;
            return __generator(this, function (_b) {
                switch (_b.label) {
                    case 0:
                        if (!true) return [3 /*break*/, 12];
                        prompt_1 = new AcEdPromptPointOptions(AcApI18n.t('jig.rect.firstPointWithOptions'));
                        addKeyword(prompt_1, 'chamfer');
                        addKeyword(prompt_1, 'elevation');
                        addKeyword(prompt_1, 'fillet');
                        addKeyword(prompt_1, 'thickness');
                        addKeyword(prompt_1, 'width');
                        return [4 /*yield*/, AcApDocManager.instance.editor.getPoint(prompt_1)];
                    case 1:
                        result = _b.sent();
                        if (result.status === AcEdPromptStatus.OK) {
                            return [2 /*return*/, result.value];
                        }
                        if (result.status !== AcEdPromptStatus.Keyword)
                            return [2 /*return*/, undefined];
                        keyword = (_a = result.stringResult) !== null && _a !== void 0 ? _a : '';
                        if (!(keyword === 'Chamfer')) return [3 /*break*/, 3];
                        return [4 /*yield*/, this.promptChamfer(settings)];
                    case 2:
                        ok = _b.sent();
                        if (!ok)
                            return [2 /*return*/, undefined];
                        return [3 /*break*/, 11];
                    case 3:
                        if (!(keyword === 'Elevation')) return [3 /*break*/, 5];
                        return [4 /*yield*/, this.promptElevation(settings)];
                    case 4:
                        ok = _b.sent();
                        if (!ok)
                            return [2 /*return*/, undefined];
                        return [3 /*break*/, 11];
                    case 5:
                        if (!(keyword === 'Fillet')) return [3 /*break*/, 7];
                        return [4 /*yield*/, this.promptFillet(settings)];
                    case 6:
                        ok = _b.sent();
                        if (!ok)
                            return [2 /*return*/, undefined];
                        return [3 /*break*/, 11];
                    case 7:
                        if (!(keyword === 'Thickness')) return [3 /*break*/, 9];
                        return [4 /*yield*/, this.promptThickness(settings)];
                    case 8:
                        ok = _b.sent();
                        if (!ok)
                            return [2 /*return*/, undefined];
                        return [3 /*break*/, 11];
                    case 9:
                        if (!(keyword === 'Width')) return [3 /*break*/, 11];
                        return [4 /*yield*/, this.promptWidth(settings)];
                    case 10:
                        ok = _b.sent();
                        if (!ok)
                            return [2 /*return*/, undefined];
                        _b.label = 11;
                    case 11: return [3 /*break*/, 0];
                    case 12: return [2 /*return*/];
                }
            });
        });
    };
    /**
     * Prompts for rectangle completion input after first corner is known.
     *
     * Supports direct opposite corner pick or switching to Area/Dimensions/Rotation
     * branches through a point-prompt state machine.
     *
     * @param context - Current application/document context.
     * @param firstPoint - First corner point.
     * @param settings - Mutable rectangle settings used by preview/build.
     * @returns Final rectangle build input, or `undefined` on cancel.
     */
    AcApRectCmd.prototype.promptSecondInput = function (context, firstPoint, settings) {
        return __awaiter(this, void 0, void 0, function () {
            var finalInput, CornerState, machine;
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0:
                        CornerState = /** @class */ (function () {
                            /**
                             * Creates corner state handler.
                             *
                             * @param cmd - Owning RECT command instance.
                             */
                            function CornerState(cmd) {
                                this.cmd = cmd;
                            }
                            /**
                             * Builds the point prompt for second-corner input.
                             *
                             * @returns Configured point prompt with keywords and preview jig.
                             */
                            CornerState.prototype.buildPrompt = function () {
                                var prompt = new AcEdPromptPointOptions(AcApI18n.t('jig.rect.otherCornerWithOptions'));
                                addKeyword(prompt, 'area');
                                addKeyword(prompt, 'dimensions');
                                addKeyword(prompt, 'rotation');
                                prompt.useDashedLine = false;
                                prompt.useBasePoint = true;
                                prompt.basePoint = new AcGePoint3d(firstPoint);
                                prompt.jig = new AcApRectJig(context.view, firstPoint, function () { return settings; });
                                return prompt;
                            };
                            /**
                             * Handles point/keyword result and drives state transitions.
                             *
                             * @param result - User input result from point prompt.
                             * @returns State-machine step result.
                             */
                            CornerState.prototype.handleResult = function (result) {
                                return __awaiter(this, void 0, void 0, function () {
                                    var keyword, ok, dims, dims;
                                    var _a;
                                    return __generator(this, function (_b) {
                                        switch (_b.label) {
                                            case 0:
                                                if (result.status === AcEdPromptStatus.OK) {
                                                    finalInput = { mode: 'corner', secondPoint: result.value };
                                                    return [2 /*return*/, 'finish'];
                                                }
                                                if (result.status !== AcEdPromptStatus.Keyword)
                                                    return [2 /*return*/, 'finish'];
                                                keyword = (_a = result.stringResult) !== null && _a !== void 0 ? _a : '';
                                                if (!(keyword === 'Rotation')) return [3 /*break*/, 2];
                                                return [4 /*yield*/, this.cmd.promptRotation(context, firstPoint, settings)];
                                            case 1:
                                                ok = _b.sent();
                                                if (!ok)
                                                    return [2 /*return*/, 'finish'];
                                                return [2 /*return*/, 'continue'];
                                            case 2:
                                                if (!(keyword === 'Dimensions')) return [3 /*break*/, 4];
                                                return [4 /*yield*/, this.cmd.promptDimensions(context, firstPoint, settings)];
                                            case 3:
                                                dims = _b.sent();
                                                if (!dims)
                                                    return [2 /*return*/, 'finish'];
                                                finalInput = dims;
                                                return [2 /*return*/, 'finish'];
                                            case 4:
                                                if (!(keyword === 'Area')) return [3 /*break*/, 6];
                                                return [4 /*yield*/, this.cmd.promptArea(context, firstPoint, settings)];
                                            case 5:
                                                dims = _b.sent();
                                                if (!dims)
                                                    return [2 /*return*/, 'finish'];
                                                finalInput = dims;
                                                return [2 /*return*/, 'finish'];
                                            case 6: return [2 /*return*/, 'continue'];
                                        }
                                    });
                                });
                            };
                            return CornerState;
                        }());
                        machine = new AcEdPromptStateMachine();
                        machine.setState(new CornerState(this));
                        return [4 /*yield*/, machine.run(function (prompt) { return AcApDocManager.instance.editor.getPoint(prompt); })];
                    case 1:
                        _a.sent();
                        return [2 /*return*/, finalInput];
                }
            });
        });
    };
    /**
     * Prompts for a strictly positive numeric value.
     *
     * @param message - Prompt message text.
     * @param jig - Optional preview jig displayed during input.
     * @returns Positive number, or `undefined` when canceled.
     */
    AcApRectCmd.prototype.promptPositiveDouble = function (message, jig) {
        return __awaiter(this, void 0, void 0, function () {
            var prompt_2, result;
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0:
                        if (!true) return [3 /*break*/, 2];
                        prompt_2 = new AcEdPromptDoubleOptions(message);
                        prompt_2.allowNegative = false;
                        prompt_2.allowZero = false;
                        if (jig)
                            prompt_2.jig = jig;
                        return [4 /*yield*/, AcApDocManager.instance.editor.getDouble(prompt_2)];
                    case 1:
                        result = _a.sent();
                        if (result.status !== AcEdPromptStatus.OK)
                            return [2 /*return*/, undefined];
                        if (isPositive(result.value))
                            return [2 /*return*/, result.value];
                        warnRectMessage('invalidPositive');
                        return [3 /*break*/, 0];
                    case 2: return [2 /*return*/];
                }
            });
        });
    };
    /**
     * Prompts chamfer distances and updates settings.
     *
     * Also clears fillet mode, because chamfer and fillet are mutually exclusive.
     *
     * @param settings - Mutable rectangle settings.
     * @returns `true` when values are accepted, otherwise `false`.
     */
    AcApRectCmd.prototype.promptChamfer = function (settings) {
        return __awaiter(this, void 0, void 0, function () {
            var d1, d2;
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0: return [4 /*yield*/, this.promptPositiveDouble(AcApI18n.t('jig.rect.chamferFirst'))];
                    case 1:
                        d1 = _a.sent();
                        if (!isPositive(d1))
                            return [2 /*return*/, false];
                        return [4 /*yield*/, this.promptPositiveDouble(AcApI18n.t('jig.rect.chamferSecond'))];
                    case 2:
                        d2 = _a.sent();
                        if (!isPositive(d2))
                            return [2 /*return*/, false];
                        settings.chamferDist1 = d1;
                        settings.chamferDist2 = d2;
                        settings.filletRadius = 0;
                        return [2 /*return*/, true];
                }
            });
        });
    };
    /**
     * Prompts fillet radius and updates settings.
     *
     * Also clears chamfer values, because fillet and chamfer are mutually exclusive.
     *
     * @param settings - Mutable rectangle settings.
     * @returns `true` when value is accepted, otherwise `false`.
     */
    AcApRectCmd.prototype.promptFillet = function (settings) {
        return __awaiter(this, void 0, void 0, function () {
            var radius;
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0: return [4 /*yield*/, this.promptPositiveDouble(AcApI18n.t('jig.rect.filletRadius'))];
                    case 1:
                        radius = _a.sent();
                        if (!isPositive(radius))
                            return [2 /*return*/, false];
                        settings.filletRadius = radius;
                        settings.chamferDist1 = 0;
                        settings.chamferDist2 = 0;
                        return [2 /*return*/, true];
                }
            });
        });
    };
    /**
     * Prompts segment width and updates settings.
     *
     * @param settings - Mutable rectangle settings.
     * @returns `true` when value is accepted, otherwise `false`.
     */
    AcApRectCmd.prototype.promptWidth = function (settings) {
        return __awaiter(this, void 0, void 0, function () {
            var prompt, result;
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0:
                        prompt = new AcEdPromptDoubleOptions(AcApI18n.t('jig.rect.segmentWidth'));
                        prompt.allowNegative = false;
                        prompt.allowZero = true;
                        return [4 /*yield*/, AcApDocManager.instance.editor.getDouble(prompt)];
                    case 1:
                        result = _a.sent();
                        if (result.status !== AcEdPromptStatus.OK)
                            return [2 /*return*/, false];
                        settings.width = normalizeNonNegative(result.value);
                        return [2 /*return*/, true];
                }
            });
        });
    };
    /**
     * Prompts elevation and updates settings.
     *
     * @param settings - Mutable rectangle settings.
     * @returns `true` when value is accepted, otherwise `false`.
     */
    AcApRectCmd.prototype.promptElevation = function (settings) {
        return __awaiter(this, void 0, void 0, function () {
            var prompt, result;
            var _a;
            return __generator(this, function (_b) {
                switch (_b.label) {
                    case 0:
                        prompt = new AcEdPromptDoubleOptions(AcApI18n.t('jig.rect.elevationValue'));
                        prompt.allowNegative = true;
                        prompt.allowZero = true;
                        return [4 /*yield*/, AcApDocManager.instance.editor.getDouble(prompt)];
                    case 1:
                        result = _b.sent();
                        if (result.status !== AcEdPromptStatus.OK)
                            return [2 /*return*/, false];
                        settings.elevation = (_a = result.value) !== null && _a !== void 0 ? _a : 0;
                        return [2 /*return*/, true];
                }
            });
        });
    };
    /**
     * Prompts thickness and updates settings.
     *
     * @param settings - Mutable rectangle settings.
     * @returns `true` when value is accepted, otherwise `false`.
     */
    AcApRectCmd.prototype.promptThickness = function (settings) {
        return __awaiter(this, void 0, void 0, function () {
            var prompt, result;
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0:
                        prompt = new AcEdPromptDoubleOptions(AcApI18n.t('jig.rect.thicknessValue'));
                        prompt.allowNegative = false;
                        prompt.allowZero = true;
                        return [4 /*yield*/, AcApDocManager.instance.editor.getDouble(prompt)];
                    case 1:
                        result = _a.sent();
                        if (result.status !== AcEdPromptStatus.OK)
                            return [2 /*return*/, false];
                        settings.thickness = normalizeNonNegative(result.value);
                        return [2 /*return*/, true];
                }
            });
        });
    };
    /**
     * Prompts rectangle rotation angle and updates settings.
     *
     * @param context - Current application/document context.
     * @param firstPoint - First corner used as angle base point.
     * @param settings - Mutable rectangle settings.
     * @returns `true` when value is accepted, otherwise `false`.
     */
    AcApRectCmd.prototype.promptRotation = function (context, firstPoint, settings) {
        return __awaiter(this, void 0, void 0, function () {
            var prompt, result;
            var _a;
            return __generator(this, function (_b) {
                switch (_b.label) {
                    case 0:
                        prompt = new AcEdPromptAngleOptions(AcApI18n.t('jig.rect.rotationAngle'));
                        prompt.useBasePoint = true;
                        prompt.useDashedLine = true;
                        prompt.basePoint = new AcGePoint3d(firstPoint);
                        prompt.allowNegative = true;
                        prompt.allowZero = true;
                        prompt.jig = new AcApRectStaticJig(context.view, firstPoint, { mode: 'dimensions', length: 1, width: 1 }, settings);
                        return [4 /*yield*/, AcApDocManager.instance.editor.getAngle(prompt)];
                    case 1:
                        result = _b.sent();
                        if (result.status !== AcEdPromptStatus.OK)
                            return [2 /*return*/, false];
                        settings.rotation = (((_a = result.value) !== null && _a !== void 0 ? _a : 0) * Math.PI) / 180;
                        return [2 /*return*/, true];
                }
            });
        });
    };
    /**
     * Prompts rectangle length and width explicitly.
     *
     * @param context - Current application/document context.
     * @param firstPoint - First corner point.
     * @param settings - Mutable rectangle settings.
     * @returns Dimension-based build input, or `undefined` on cancel.
     */
    AcApRectCmd.prototype.promptDimensions = function (context, firstPoint, settings) {
        return __awaiter(this, void 0, void 0, function () {
            var seedInput, length, width;
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0:
                        seedInput = {
                            mode: 'dimensions',
                            length: 1,
                            width: 1
                        };
                        return [4 /*yield*/, this.promptPositiveDouble(AcApI18n.t('jig.rect.dimensionLength'), new AcApRectStaticJig(context.view, firstPoint, seedInput, settings))];
                    case 1:
                        length = _a.sent();
                        if (!isPositive(length))
                            return [2 /*return*/, undefined];
                        return [4 /*yield*/, this.promptPositiveDouble(AcApI18n.t('jig.rect.dimensionWidth'), new AcApRectStaticJig(context.view, firstPoint, { mode: 'dimensions', length: length, width: 1 }, settings))];
                    case 2:
                        width = _a.sent();
                        if (!isPositive(width))
                            return [2 /*return*/, undefined];
                        return [2 /*return*/, {
                                mode: 'dimensions',
                                length: length,
                                width: width
                            }];
                }
            });
        });
    };
    /**
     * Prompts rectangle area, then asks for either known length or known width.
     *
     * @param context - Current application/document context.
     * @param firstPoint - First corner point.
     * @param settings - Mutable rectangle settings.
     * @returns Dimension-based build input derived from area, or `undefined`.
     */
    AcApRectCmd.prototype.promptArea = function (context, firstPoint, settings) {
        return __awaiter(this, void 0, void 0, function () {
            var area, knownPrompt, knownResult, width, length;
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0: return [4 /*yield*/, this.promptPositiveDouble(AcApI18n.t('jig.rect.areaValue'), new AcApRectStaticJig(context.view, firstPoint, { mode: 'dimensions', length: 1, width: 1 }, settings))];
                    case 1:
                        area = _a.sent();
                        if (!isPositive(area))
                            return [2 /*return*/, undefined];
                        knownPrompt = new AcEdPromptDoubleOptions(AcApI18n.t('jig.rect.areaLengthOrWidth'));
                        addDoubleKeyword(knownPrompt, 'rectWidth');
                        knownPrompt.allowNegative = false;
                        knownPrompt.allowZero = false;
                        knownPrompt.jig = new AcApRectStaticJig(context.view, firstPoint, { mode: 'dimensions', length: 1, width: 1 }, settings);
                        return [4 /*yield*/, AcApDocManager.instance.editor.getDouble(knownPrompt)];
                    case 2:
                        knownResult = _a.sent();
                        if (!(knownResult.status === AcEdPromptStatus.Keyword)) return [3 /*break*/, 4];
                        if (knownResult.stringResult !== 'Width')
                            return [2 /*return*/, undefined];
                        return [4 /*yield*/, this.promptPositiveDouble(AcApI18n.t('jig.rect.areaSpecifyWidth'), new AcApRectStaticJig(context.view, firstPoint, { mode: 'dimensions', length: 1, width: 1 }, settings))];
                    case 3:
                        width = _a.sent();
                        if (!isPositive(width))
                            return [2 /*return*/, undefined];
                        return [2 /*return*/, {
                                mode: 'dimensions',
                                length: (area !== null && area !== void 0 ? area : 0) / (width !== null && width !== void 0 ? width : 1),
                                width: width
                            }];
                    case 4:
                        if (knownResult.status !== AcEdPromptStatus.OK)
                            return [2 /*return*/, undefined];
                        if (!isPositive(knownResult.value))
                            return [2 /*return*/, undefined];
                        length = knownResult.value;
                        return [2 /*return*/, {
                                mode: 'dimensions',
                                length: length,
                                width: (area !== null && area !== void 0 ? area : 0) / length
                            }];
                }
            });
        });
    };
    /**
     * Last-used rectangle settings persisted between command invocations.
     */
    AcApRectCmd._settings = cloneRectSettings(DEFAULT_RECT_SETTINGS);
    return AcApRectCmd;
}(AcEdCommand));
export { AcApRectCmd };
//# sourceMappingURL=AcApRectCmd.js.map