"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
    var ownKeys = function(o) {
        ownKeys = Object.getOwnPropertyNames || function (o) {
            var ar = [];
            for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
            return ar;
        };
        return ownKeys(o);
    };
    return function (mod) {
        if (mod && mod.__esModule) return mod;
        var result = {};
        if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
        __setModuleDefault(result, mod);
        return result;
    };
})();
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.collectColumnFixedWidths = collectColumnFixedWidths;
exports._resetMeasureContext = _resetMeasureContext;
exports.calculateOperateColumnWidth = calculateOperateColumnWidth;
exports.calculateAutoWidths = calculateAutoWidths;
exports.distributeRemainingWidth = distributeRemainingWidth;
exports.useAutoColumnWidth = useAutoColumnWidth;
const i18n_1 = __importDefault(require("../../../../../../locales/i18n.js"));
/**
 * 表格列自动宽度：用 canvas 测量表头与单元格文案宽度，得到各列建议宽度；
 * 可选将容器剩余宽度均分给「可伸缩」列（fillContainerWidth 为 true 时）。
 */
const React = __importStar(require("react"));
/** 普通列自动宽度下限（px），与测量结果取 max 后作为最终列宽 */
const DEFAULT_MIN_WIDTH = 150;
/** 普通列自动宽度上限（px），calculateAutoWidths 默认 maxWidth */
const DEFAULT_MAX_WIDTH = 460;
/** th/td 共有的额外宽度（padding: 0 12px = 24px + border-right 1px = 25px） */
const DEFAULT_ADDITIONAL_WIDTH = 25;
/** 表头独有的额外占位（icon 16px + gap 6px + .ai-table-header-content padding-right 8px = 30px） */
const DEFAULT_HEADER_EXTRA_WIDTH = 30;
/** .ai-table-header-content padding-right（px），用于 getHeaderExtraWidth 计算 */
const HEADER_CONTENT_PADDING_RIGHT = 8;
/** .ai-table-header-content gap（px），用于 getHeaderExtraWidth 计算 */
const HEADER_CONTENT_GAP = 6;
/** 自适应采样的行数阈值：超过此数量时自动降低采样率 */
const ADAPTIVE_SAMPLE_THRESHOLD = 200;
/** 自适应采样率：行数超过阈值时使用的默认采样率 */
const ADAPTIVE_SAMPLE_RATE = 0.3;
/** measureText 使用的字体，需与表格实际渲染字体接近以减少误差 */
const DEFAULT_FONT_FAMILY = 'Arial, sans-serif';
/** 无法得到有效测量结果时的列宽兜底值（px） */
const DEFAULT_FALLBACK_WIDTH = 200;
/** 操作列最小宽度；无测量上下文（canvas）时的默认列宽（px） */
const DEFAULT_OPERATE_COLUMN_WIDTH = 150;
/** 操作按钮未配置 widthRule.additionWidth 时，叠加在文本宽度上的默认边距（px） */
const DEFAULT_OPERATE_BUTTON_PADDING_WIDTH = 16;
/** 操作列计算时默认的 additionalWidth（表头/单元格左右内边距等，px） */
const DEFAULT_OPERATE_COLUMN_PADDING_WIDTH = 16;
/** 按钮超出 showButtonNum 时用于测量「更多」入口宽度的文案 */
const DEFAULT_MORE_BUTTON_TEXT = i18n_1.default.get({ id: 'More', dm: '更多' });
/** 列唯一标识，与数据字段路径一致 */
function getColumnKey(column) {
    return String((column === null || column === void 0 ? void 0 : column.id) || (column === null || column === void 0 ? void 0 : column.accessorKey) || (column === null || column === void 0 ? void 0 : column.dataIndex) || (column === null || column === void 0 ? void 0 : column.columnCode) || '');
}
/** 列配置中的固定 width（数字串），大于 0 表示不参与自动宽度 */
function getColumnFixedWidth(column) {
    const fixedWidth = parseInt(column === null || column === void 0 ? void 0 : column.width, 10);
    return fixedWidth > 0 ? fixedWidth : 0;
}
/**
 * 从列配置中收集所有显式设置了 width 的列，返回 key → px 映射。
 * 用于在 columnsAutoWidth=false 时也能让 column.width 生效。
 */
function collectColumnFixedWidths(columns) {
    if (!Array.isArray(columns))
        return {};
    const result = {};
    for (const column of columns) {
        const key = getColumnKey(column);
        if (!key)
            continue;
        const fixedWidth = getColumnFixedWidth(column);
        if (fixedWidth > 0) {
            result[key] = fixedWidth;
        }
    }
    return result;
}
/** 是否可参与「剩余宽度均分」：无持久化宽度、非固定列、且未关闭 enableAutoWidth */
function canColumnReceiveRemainingWidth(column, persistedWidthMap) {
    const key = getColumnKey(column);
    if (!key || persistedWidthMap[key] > 0)
        return false;
    if (getColumnFixedWidth(column) > 0)
        return false;
    return (column === null || column === void 0 ? void 0 : column.enableAutoWidth) !== false;
}
/** 表头展示文案，优先 contentWidthRule.header.text */
function getHeaderText(column) {
    var _a, _b, _c, _d, _e;
    const headerTextRule = (_b = (_a = column === null || column === void 0 ? void 0 : column.contentWidthRule) === null || _a === void 0 ? void 0 : _a.header) === null || _b === void 0 ? void 0 : _b.text;
    if (typeof headerTextRule === 'function') {
        return String((_c = headerTextRule(column)) !== null && _c !== void 0 ? _c : '');
    }
    if (headerTextRule != null) {
        return String(headerTextRule);
    }
    const header = column === null || column === void 0 ? void 0 : column.header;
    if (typeof header === 'string' || typeof header === 'number') {
        return String(header);
    }
    return String((_e = (_d = column === null || column === void 0 ? void 0 : column.name) !== null && _d !== void 0 ? _d : column === null || column === void 0 ? void 0 : column.title) !== null && _e !== void 0 ? _e : '');
}
/** 按列 key 取单元格值；支持 a.b 嵌套路径 */
function getValueByPath(record, key) {
    if (!record || !key)
        return undefined;
    const directValue = record[key];
    if (directValue !== undefined && directValue !== null) {
        return directValue;
    }
    return key.split('.').reduce((prev, curr) => prev === null || prev === void 0 ? void 0 : prev[curr], record);
}
/** contentWidthRule 上配置的 additionWidth（图标等额外占位，px） */
function getRuleAdditionWidth(rule, value, rowIndex, record) {
    const additionWidth = rule === null || rule === void 0 ? void 0 : rule.additionWidth;
    const result = typeof additionWidth === 'function' ? additionWidth(value, rowIndex, record) : additionWidth;
    const parsed = parseInt(result, 10);
    return Number.isFinite(parsed) ? parsed : 0;
}
/**
 * 表头独有的额外占位宽度（icon + gap + .header-content padding-right）。
 * contentWidthRule.header.iconWidth 可按列覆盖图标部分，false/0 表示无图标。
 */
function getHeaderExtraWidth(column, defaultExtraWidth) {
    var _a, _b;
    const iconWidth = (_b = (_a = column === null || column === void 0 ? void 0 : column.contentWidthRule) === null || _a === void 0 ? void 0 : _a.header) === null || _b === void 0 ? void 0 : _b.iconWidth;
    if (iconWidth === false)
        return HEADER_CONTENT_PADDING_RIGHT;
    if (iconWidth != null) {
        const parsed = parseInt(iconWidth, 10);
        if (Number.isFinite(parsed) && parsed >= 0) {
            return parsed + HEADER_CONTENT_GAP + HEADER_CONTENT_PADDING_RIGHT;
        }
    }
    return defaultExtraWidth;
}
/**
 * 单元格用于测宽的文案列表及附加宽度；
 * text 可为数组（如多行/多段），与 contentWidthRule.cell 一致。
 */
function getCellTexts(column, record, rowIndex) {
    var _a, _b;
    const key = getColumnKey(column);
    const value = getValueByPath(record, key);
    const rule = (_b = (_a = column === null || column === void 0 ? void 0 : column.contentWidthRule) === null || _a === void 0 ? void 0 : _a.cell) !== null && _b !== void 0 ? _b : column === null || column === void 0 ? void 0 : column.contentWidthRule;
    const textRule = rule === null || rule === void 0 ? void 0 : rule.text;
    const text = typeof textRule === 'function'
        ? textRule(value, rowIndex, record)
        : textRule != null
            ? textRule
            : value;
    if (Array.isArray(text)) {
        return {
            texts: text.map((item) => String(item !== null && item !== void 0 ? item : '')),
            additionWidth: getRuleAdditionWidth(rule, value, rowIndex, record),
        };
    }
    return {
        texts: [String(text !== null && text !== void 0 ? text : '')],
        additionWidth: getRuleAdditionWidth(rule, value, rowIndex, record),
    };
}
/** 复用 canvas 上下文用于 measureText；SSR 无 document 时返回 null */
let _cachedMeasureContext;
function getMeasureContext() {
    if (_cachedMeasureContext !== undefined)
        return _cachedMeasureContext;
    if (typeof document === 'undefined') {
        _cachedMeasureContext = null;
        return null;
    }
    const canvas = document.createElement('canvas');
    _cachedMeasureContext = canvas.getContext('2d');
    return _cachedMeasureContext;
}
/** @internal 仅用于测试：重置缓存的 canvas context，使下次调用重新创建 */
function _resetMeasureContext() {
    _cachedMeasureContext = undefined;
}
/** 按粗体给定字号测量字符串像素宽度 */
function measureText(context, text, fontSize, fontFamily = DEFAULT_FONT_FAMILY) {
    context.font = `bold ${fontSize}px ${fontFamily}`;
    return context.measureText(text).width;
}
/** 从 React 节点树中抽出纯文本，供操作列按钮测宽 */
function extractReactText(node) {
    var _a;
    if (node == null || typeof node === 'boolean')
        return '';
    if (typeof node === 'string' || typeof node === 'number')
        return String(node);
    if (Array.isArray(node)) {
        return node.map(extractReactText).filter(Boolean).join('');
    }
    if (React.isValidElement(node)) {
        return extractReactText((_a = node.props) === null || _a === void 0 ? void 0 : _a.children);
    }
    return '';
}
/** 操作列单个按钮的展示文案（widthRule.text / children / 函数渲染） */
function getOperateButtonText(button, row, rowIndex) {
    var _a, _b;
    if (typeof button === 'function') {
        return extractReactText(button(row, rowIndex));
    }
    const textRule = (_a = button === null || button === void 0 ? void 0 : button.widthRule) === null || _a === void 0 ? void 0 : _a.text;
    if (typeof textRule === 'function') {
        return String((_b = textRule(row, rowIndex)) !== null && _b !== void 0 ? _b : '');
    }
    if (textRule != null) {
        return String(textRule);
    }
    const { children } = button || {};
    if (typeof children === 'function') {
        return extractReactText(children(row, rowIndex));
    }
    return extractReactText(children);
}
/** 按钮在文本宽度之外的附加宽度（widthRule.additionWidth） */
function getOperateButtonAdditionWidth(button, row, rowIndex) {
    var _a;
    const additionWidth = (_a = button === null || button === void 0 ? void 0 : button.widthRule) === null || _a === void 0 ? void 0 : _a.additionWidth;
    const result = typeof additionWidth === 'function' ? additionWidth(row, rowIndex) : additionWidth;
    const parsed = parseInt(result, 10);
    return Number.isFinite(parsed) ? parsed : DEFAULT_OPERATE_BUTTON_PADDING_WIDTH;
}
/** 操作按钮是否在当前行展示（visible 为函数时） */
function isOperateButtonVisible(button, row, rowIndex) {
    if (button &&
        typeof button === 'object' &&
        typeof button.visible === 'function' &&
        !button.visible(row, rowIndex)) {
        return false;
    }
    return true;
}
/** 操作列允许的最大宽度：false 表示不限制 */
function getOperateColumnMaxWidth(operateColumn, options) {
    var _a;
    if ((operateColumn === null || operateColumn === void 0 ? void 0 : operateColumn.maxWidth) === false) {
        return Infinity;
    }
    if (Number(operateColumn === null || operateColumn === void 0 ? void 0 : operateColumn.maxWidth) > 0) {
        return Number(operateColumn.maxWidth);
    }
    return (_a = options === null || options === void 0 ? void 0 : options.maxWidth) !== null && _a !== void 0 ? _a : DEFAULT_MAX_WIDTH;
}
/**
 * 计算操作列宽度：按表头与各可见行按钮（含「更多」）文本测量，取最大内容宽并 clamp。
 * 无按钮或配置了固定 width 时走短路逻辑。
 */
function calculateOperateColumnWidth({ operateColumn, dataSource, options, }) {
    var _a, _b;
    if (!Array.isArray(operateColumn === null || operateColumn === void 0 ? void 0 : operateColumn.buttons) || operateColumn.buttons.length === 0) {
        return 0;
    }
    const fixedWidth = parseInt(operateColumn.width, 10);
    if (fixedWidth > 0) {
        return fixedWidth;
    }
    const context = getMeasureContext();
    if (!context) {
        return DEFAULT_OPERATE_COLUMN_WIDTH;
    }
    const { headerFontSize = 12, cellFontSize = 12, additionalWidth = DEFAULT_OPERATE_COLUMN_PADDING_WIDTH, } = options || {};
    const maxWidth = getOperateColumnMaxWidth(operateColumn, options);
    const splitWidth = parseInt(String(operateColumn.splitWidth), 10) || 10;
    const buttons = operateColumn.buttons;
    const rows = (dataSource === null || dataSource === void 0 ? void 0 : dataSource.length) ? dataSource : [{}];
    const title = (_b = (_a = operateColumn.title) !== null && _a !== void 0 ? _a : operateColumn.name) !== null && _b !== void 0 ? _b : i18n_1.default.get({ id: 'ActionsOperation', dm: '操作' });
    let maxContentWidth = measureText(context, String(title), headerFontSize);
    for (let rowIndex = 0; rowIndex < rows.length; rowIndex += 1) {
        const row = rows[rowIndex];
        let showButtonNumReality = Number(operateColumn.showButtonNum) > 0
            ? Number(operateColumn.showButtonNum)
            : buttons.length;
        // 若按 showButtonNum 只会收起 1 个按钮，则多展示一个，避免仅多出一个「更多」的窄列
        if (buttons.length - showButtonNumReality === 1) {
            showButtonNumReality += 1;
        }
        const visibleButtons = buttons.filter((button) => isOperateButtonVisible(button, row, rowIndex));
        const showButtons = visibleButtons.slice(0, showButtonNumReality);
        const hasMoreButton = visibleButtons.length > showButtons.length;
        const measureItems = hasMoreButton
            ? [...showButtons, { children: DEFAULT_MORE_BUTTON_TEXT }]
            : showButtons;
        const rowWidth = measureItems.reduce((sum, button, index) => {
            const textWidth = measureText(context, getOperateButtonText(button, row, rowIndex), cellFontSize);
            const buttonWidth = textWidth + getOperateButtonAdditionWidth(button, row, rowIndex);
            return sum + buttonWidth + (index > 0 ? splitWidth : 0);
        }, 0);
        maxContentWidth = Math.max(maxContentWidth, rowWidth);
    }
    return Math.ceil(Math.max(Math.min(maxContentWidth + additionalWidth, maxWidth), DEFAULT_OPERATE_COLUMN_WIDTH));
}
/**
 * 为「启用自动宽度且非固定列、无持久化宽度」的列计算建议宽度（key -> px）。
 * 无 canvas 环境时返回空对象。
 */
function calculateAutoWidths({ columns, dataSource, persistedWidthMap, options, }) {
    var _a, _b;
    if (!Array.isArray(columns) || columns.length === 0) {
        return {};
    }
    const { headerFontSize = 12, cellFontSize = 12, sampleRate: rawSampleRate, additionalWidth = DEFAULT_ADDITIONAL_WIDTH, headerExtraWidth = DEFAULT_HEADER_EXTRA_WIDTH, maxWidth = DEFAULT_MAX_WIDTH, getCustomWidth, } = options || {};
    const sampleRate = rawSampleRate !== null && rawSampleRate !== void 0 ? rawSampleRate : (((dataSource === null || dataSource === void 0 ? void 0 : dataSource.length) || 0) > ADAPTIVE_SAMPLE_THRESHOLD ? ADAPTIVE_SAMPLE_RATE : 1);
    const context = getMeasureContext();
    if (!context) {
        return {};
    }
    const widths = {};
    const headerWidths = {};
    const columnsToMeasure = columns.filter((column) => {
        const key = getColumnKey(column);
        if (!key || persistedWidthMap[key] > 0)
            return false;
        const fixedWidth = parseInt(column === null || column === void 0 ? void 0 : column.width, 10);
        if (fixedWidth > 0) {
            widths[key] = fixedWidth;
            return false;
        }
        return (column === null || column === void 0 ? void 0 : column.enableAutoWidth) !== false;
    });
    for (const column of columnsToMeasure) {
        const key = getColumnKey(column);
        const headerAddition = getRuleAdditionWidth((_a = column === null || column === void 0 ? void 0 : column.contentWidthRule) === null || _a === void 0 ? void 0 : _a.header, column, 0, column);
        const headerWidth = measureText(context, getHeaderText(column), headerFontSize) +
            headerAddition +
            getHeaderExtraWidth(column, headerExtraWidth);
        headerWidths[key] = headerWidth;
        const step = Math.max(1, Math.ceil(1 / Math.max(sampleRate || 1, 0.01)));
        let maxCellWidth = 0;
        for (let rowIndex = 0; rowIndex < ((dataSource === null || dataSource === void 0 ? void 0 : dataSource.length) || 0); rowIndex += step) {
            const row = dataSource[rowIndex];
            const { texts, additionWidth: cellAdditionWidth } = getCellTexts(column, row, rowIndex);
            for (const text of texts) {
                const cellWidth = measureText(context, text, cellFontSize) + cellAdditionWidth;
                if (cellWidth > maxCellWidth) {
                    maxCellWidth = cellWidth;
                }
            }
        }
        const columnMaxWidth = (column === null || column === void 0 ? void 0 : column.maxWidth) === false
            ? Infinity
            : Number(column === null || column === void 0 ? void 0 : column.maxWidth) > 0
                ? Number(column.maxWidth)
                : maxWidth;
        const rawWidth = Math.max(headerWidth, maxCellWidth) + additionalWidth;
        const clampedWidth = Math.max(Math.min(rawWidth, columnMaxWidth), DEFAULT_MIN_WIDTH);
        widths[key] =
            (_b = getCustomWidth === null || getCustomWidth === void 0 ? void 0 : getCustomWidth(clampedWidth, key, {
                columns,
                headerWidths,
                textWidth: maxCellWidth,
                additionalWidth,
                itemMaxWidth: columnMaxWidth,
            })) !== null && _b !== void 0 ? _b : Math.ceil(clampedWidth);
    }
    return widths;
}
/**
 * 在容器宽度大于各列当前宽度之和时，将剩余像素均分给可伸缩列（向下取整，余数前若干列 +1）。
 * 无有效容器宽度或无可伸缩列时原样返回 widthMap。
 */
function distributeRemainingWidth({ columns, widthMap, persistedWidthMap, containerWidth, reservedWidth = 0, }) {
    if (!containerWidth || containerWidth <= 0 || !Array.isArray(columns) || columns.length === 0) {
        return widthMap;
    }
    const columnWidths = columns.map((column) => {
        const key = getColumnKey(column);
        return {
            key,
            width: (key && persistedWidthMap[key]) ||
                (key && widthMap[key]) ||
                getColumnFixedWidth(column) ||
                DEFAULT_FALLBACK_WIDTH,
            canGrow: canColumnReceiveRemainingWidth(column, persistedWidthMap),
        };
    });
    const growableColumns = columnWidths.filter((column) => column.key && column.canGrow);
    if (growableColumns.length === 0) {
        return widthMap;
    }
    const totalWidth = reservedWidth + columnWidths.reduce((sum, column) => sum + column.width, 0);
    const remainingWidth = Math.floor(containerWidth - totalWidth);
    if (remainingWidth <= 0) {
        return widthMap;
    }
    const nextWidthMap = { ...widthMap };
    const baseIncrement = Math.floor(remainingWidth / growableColumns.length);
    let remainder = remainingWidth % growableColumns.length;
    for (const column of growableColumns) {
        const increment = baseIncrement + (remainder > 0 ? 1 : 0);
        remainder -= 1;
        nextWidthMap[column.key] = column.width + increment;
    }
    return nextWidthMap;
}
/** options 浅比较：所有自有属性值 === 则视为相同 */
function shallowEqualOptions(a, b) {
    if (a === b)
        return true;
    if (!a || !b)
        return false;
    const aKeys = Object.keys(a);
    const bKeys = Object.keys(b);
    if (aKeys.length !== bKeys.length)
        return false;
    return aKeys.every((key) => a[key] === b[key]);
}
/**
 * 仅在开发模式下对高风险参数输出警告，帮助接入方尽早发现配置问题。
 * 生产环境不输出任何内容，不改变任何行为。
 */
function warnInDev(options) {
    if (process.env.NODE_ENV === 'production')
        return;
    if (!options)
        return;
    if (typeof options.getCustomWidth === 'function') {
        // eslint-disable-next-line no-console
        console.warn('[CnAiTable] columnsAutoWidthOpt.getCustomWidth 是专家参数：' +
            '请确保该函数是幂等的（相同输入始终返回相同输出），否则会导致列宽反复抖动。' +
            '若只需固定某列宽度，推荐直接在列配置中使用 width 字段。');
    }
    if (typeof options.sampleRate === 'number' && options.sampleRate <= 0) {
        // eslint-disable-next-line no-console
        console.warn('[CnAiTable] columnsAutoWidthOpt.sampleRate 不能为 0 或负数，' +
            '已触发内部保护（等价极低采样率），可能导致测宽严重偏差。请传入 0.1 ~ 1 之间的值。');
    }
}
/**
 * 在客户端根据列与数据计算自动列宽。
 * - 测量层（measureText）与分配层（distributeRemainingWidth）分离缓存；
 *   resize 只改变 containerWidth 时不会重新测量，仅重新分配。
 * - 使用 useMemo 同步计算，消除首帧空 widthMap 导致的闪烁。
 */
function useAutoColumnWidth({ enabled, columns, dataSource, persistedWidthMap, options, containerWidth, reservedWidth, }) {
    const stableOptionsRef = React.useRef(options);
    if (!shallowEqualOptions(stableOptionsRef.current, options)) {
        stableOptionsRef.current = options;
    }
    const stableOptions = stableOptionsRef.current;
    React.useEffect(() => {
        if (enabled)
            warnInDev(stableOptions);
        // options 稳定引用变化时重新检查，mount 时也检查一次
        // eslint-disable-next-line react-hooks/exhaustive-deps
    }, [enabled, stableOptions]);
    const measuredWidthMap = React.useMemo(() => {
        if (!enabled)
            return {};
        return calculateAutoWidths({
            columns,
            dataSource,
            persistedWidthMap,
            options: stableOptions,
        });
    }, [enabled, columns, dataSource, persistedWidthMap, stableOptions]);
    const autoWidthMap = React.useMemo(() => {
        if (!enabled)
            return {};
        if ((stableOptions === null || stableOptions === void 0 ? void 0 : stableOptions.fillContainerWidth) === false)
            return measuredWidthMap;
        return distributeRemainingWidth({
            columns,
            widthMap: measuredWidthMap,
            persistedWidthMap,
            containerWidth,
            reservedWidth,
        });
    }, [enabled, measuredWidthMap, columns, persistedWidthMap, stableOptions, containerWidth, reservedWidth]);
    return autoWidthMap;
}
