import { __decorate } from "tslib";
import { DesignSystem } from '@ni/fast-foundation';
import { attr, nullableNumberConverter, Observable, observable } from '@ni/fast-element';
import { styles } from '../base/styles';
import { template } from './template';
import { TableColumnAlignment } from '../../table/types';
import { TableColumnTextBase, mixinTextBase } from '../text-base';
import { TableColumnSortOperation } from '../base/types';
import { tableColumnNumberTextGroupHeaderTag } from './group-header-view';
import { tableColumnNumberTextCellViewTag } from './cell-view';
import { NumberTextAlignment, NumberTextFormat } from './types';
import { UnitFormatNumberText } from './models/unit-format-number-text';
import { TableColumnNumberTextValidator } from './models/table-column-number-text-validator';
import { lang } from '../../theme-provider';
import { Unit } from '../../unit/base/unit';
import { waitUntilCustomElementsDefinedAsync } from '../../utilities/wait-until-custom-elements-defined-async';
/**
 * The table column for displaying numbers as text.
 */
export class TableColumnNumberText extends mixinTextBase((TableColumnTextBase)) {
    constructor() {
        super(...arguments);
        this.langSubscriber = {
            handleChange: () => {
                this.updateColumnConfig();
            }
        };
        this.unitSubscriber = {
            handleChange: () => {
                this.updateColumnConfig();
            }
        };
    }
    connectedCallback() {
        super.connectedCallback();
        lang.subscribe(this.langSubscriber, this);
        this.updateColumnConfig();
    }
    disconnectedCallback() {
        super.disconnectedCallback();
        lang.unsubscribe(this.langSubscriber, this);
    }
    placeholderChanged() {
        this.updateColumnConfig();
    }
    getColumnInternalsOptions() {
        return {
            cellRecordFieldNames: ['value'],
            cellViewTag: tableColumnNumberTextCellViewTag,
            groupHeaderViewTag: tableColumnNumberTextGroupHeaderTag,
            delegatedEvents: [],
            sortOperation: TableColumnSortOperation.basic,
            validator: new TableColumnNumberTextValidator()
        };
    }
    updateUnitNotifier() {
        if (this.unitNotifier) {
            this.unitNotifier.unsubscribe(this.unitSubscriber);
            this.unitNotifier = undefined;
        }
        if (this.unit) {
            const notifier = Observable.getNotifier(this.unit);
            notifier.subscribe(this.unitSubscriber, 'resolvedUnitScale');
            this.unitNotifier = notifier;
        }
    }
    formatChanged() {
        this.updateColumnConfig();
    }
    alignmentChanged() {
        this.updateColumnConfig();
    }
    decimalDigitsChanged() {
        this.updateColumnConfig();
    }
    decimalMaximumDigitsChanged() {
        this.updateColumnConfig();
    }
    unitElementsChanged() {
        void this.updateUnit();
    }
    async updateUnit() {
        this.unit = undefined;
        if (this.unitElements) {
            await waitUntilCustomElementsDefinedAsync(this.unitElements);
            this.unit = this.unitElements.find((x) => x instanceof Unit);
        }
        this.updateUnitNotifier();
    }
    unitChanged() {
        this.updateColumnConfig();
    }
    updateColumnConfig() {
        const validator = this.columnInternals.validator;
        validator.validateDecimalDigits(this.format, this.decimalDigits);
        validator.validateDecimalMaximumDigits(this.format, this.decimalMaximumDigits);
        validator.validateNoMutuallyExclusiveProperties(this.format, this.decimalDigits, this.decimalMaximumDigits);
        validator.validateAtMostOneUnit(this.unitElements ?? []);
        if (validator.isValid()) {
            const columnConfig = {
                formatter: this.createFormatter(),
                alignment: this.determineCellContentAlignment(),
                placeholder: this.placeholder
            };
            this.columnInternals.headerAlignment = columnConfig.alignment;
            this.columnInternals.columnConfig = columnConfig;
        }
        else {
            this.columnInternals.columnConfig = undefined;
        }
    }
    createFormatter() {
        const unitScale = this.unit?.resolvedUnitScale;
        return new UnitFormatNumberText(lang.getValueFor(this), {
            // Attribute values sometimes resolve to either null or undefined
            // See https://github.com/microsoft/fast/issues/6630
            numberTextFormat: this.format ?? undefined,
            decimalDigits: this.decimalDigits ?? undefined,
            decimalMaximumDigits: this.decimalMaximumDigits ?? undefined,
            unitScale
        });
    }
    determineCellContentAlignment() {
        if (this.alignment === NumberTextAlignment.left) {
            return TableColumnAlignment.left;
        }
        if (this.alignment === NumberTextAlignment.right) {
            return TableColumnAlignment.right;
        }
        // Look at format and decimal max digits and unit to determine the default alignment
        if (this.format === NumberTextFormat.decimal
            && typeof this.decimalMaximumDigits !== 'number'
            && !this.unit) {
            return TableColumnAlignment.right;
        }
        return TableColumnAlignment.left;
    }
}
__decorate([
    attr
], TableColumnNumberText.prototype, "format", void 0);
__decorate([
    attr
], TableColumnNumberText.prototype, "alignment", void 0);
__decorate([
    attr({ attribute: 'decimal-digits', converter: nullableNumberConverter })
], TableColumnNumberText.prototype, "decimalDigits", void 0);
__decorate([
    attr({
        attribute: 'decimal-maximum-digits',
        converter: nullableNumberConverter
    })
], TableColumnNumberText.prototype, "decimalMaximumDigits", void 0);
__decorate([
    observable
], TableColumnNumberText.prototype, "unitElements", void 0);
__decorate([
    observable
], TableColumnNumberText.prototype, "unit", void 0);
const nimbleTableColumnNumberText = TableColumnNumberText.compose({
    baseName: 'table-column-number-text',
    template,
    styles
});
DesignSystem.getOrCreate()
    .withPrefix('nimble')
    .register(nimbleTableColumnNumberText());
export const tableColumnNumberTextTag = 'nimble-table-column-number-text';
//# sourceMappingURL=index.js.map