import { input, textarea, select, option } from "../../../core/dom";
import { isInteger, isString } from "../../../core/util/types";
import { DOMComponentView } from "../../../core/dom_view";
import { Model } from "../../../model";
import { DTINDEX_NAME } from "./definitions";
import * as tables from "../../../styles/widgets/tables.css";
export class CellEditorView extends DOMComponentView {
    static __name__ = "CellEditorView";
    defaultValue;
    get emptyValue() {
        return null;
    }
    inputEl;
    args;
    constructor(options) {
        const { model, parent } = options.column;
        super({ model, parent, ...options });
        this.args = options;
        this.initialize(); // XXX: no build_views()
        this.render(); // XXX: this isn't governed by layout
    }
    initialize() {
        super.initialize();
        this.inputEl = this._createInput();
        this.defaultValue = null;
    }
    async lazy_initialize() {
        throw new Error("unsupported");
    }
    css_classes() {
        return super.css_classes().concat(tables.cell_editor);
    }
    render() {
        this.args.container.append(this.el);
        this.shadow_el.appendChild(this.inputEl);
        this.renderEditor();
        this.disableNavigation();
    }
    renderEditor() { }
    disableNavigation() {
        // XXX: without cast `event` is of non-specific type `Event`
        this.inputEl.addEventListener("keydown", (event) => {
            switch (event.key) {
                case "ArrowLeft":
                case "ArrowRight":
                case "ArrowUp":
                case "ArrowDown":
                case "PageUp":
                case "PageDown": {
                    event.stopImmediatePropagation();
                    break;
                }
            }
        });
    }
    destroy() {
        this.remove();
    }
    focus() {
        this.inputEl.focus();
    }
    show() { }
    hide() { }
    position() { }
    getValue() {
        return this.inputEl.value;
    }
    setValue(val) {
        this.inputEl.value = val;
    }
    serializeValue() {
        return this.getValue();
    }
    isValueChanged() {
        return !(this.getValue() == "" && this.defaultValue == null) && this.getValue() !== this.defaultValue;
    }
    applyValue(item, state) {
        const grid_data = this.args.grid.getData();
        const offset = grid_data.index.indexOf(item[DTINDEX_NAME]);
        grid_data.setField(offset, this.args.column.field, state);
    }
    loadValue(item) {
        const value = item[this.args.column.field];
        this.defaultValue = value != null ? value : this.emptyValue;
        this.setValue(this.defaultValue);
    }
    validateValue(value) {
        if (this.args.column.validator) {
            const result = this.args.column.validator(value);
            if (!result.valid) {
                return result;
            }
        }
        return { valid: true, msg: null };
    }
    validate() {
        return this.validateValue(this.getValue());
    }
}
export class CellEditor extends Model {
    static __name__ = "CellEditor";
}
export class StringEditorView extends CellEditorView {
    static __name__ = "StringEditorView";
    get emptyValue() {
        return "";
    }
    _createInput() {
        return input({ type: "text" });
    }
    renderEditor() {
        //completions = @model.completions
        //if completions.length != 0
        //  @inputEl.classList.add("bk-cell-editor-completion")
        //  $(@inputEl).autocomplete({source: completions})
        //  $(@inputEl).autocomplete("widget")
        this.inputEl.focus();
        this.inputEl.select();
    }
    loadValue(item) {
        super.loadValue(item);
        this.inputEl.defaultValue = this.defaultValue;
        this.inputEl.select();
    }
}
export class StringEditor extends CellEditor {
    static __name__ = "StringEditor";
    static {
        this.prototype.default_view = StringEditorView;
        this.define(({ Str, List }) => ({
            completions: [List(Str), []],
        }));
    }
}
export class TextEditorView extends CellEditorView {
    static __name__ = "TextEditorView";
    _createInput() {
        return textarea();
    }
    renderEditor() {
        this.inputEl.focus();
        this.inputEl.select();
    }
}
export class TextEditor extends CellEditor {
    static __name__ = "TextEditor";
    static {
        this.prototype.default_view = TextEditorView;
    }
}
export class SelectEditorView extends CellEditorView {
    static __name__ = "SelectEditorView";
    _createInput() {
        return select();
    }
    renderEditor() {
        for (const opt of this.model.options) {
            this.inputEl.appendChild(option({ value: opt }, opt));
        }
        this.focus();
    }
}
export class SelectEditor extends CellEditor {
    static __name__ = "SelectEditor";
    static {
        this.prototype.default_view = SelectEditorView;
        this.define(({ Str, List }) => ({
            options: [List(Str), []],
        }));
    }
}
export class PercentEditorView extends CellEditorView {
    static __name__ = "PercentEditorView";
    _createInput() {
        return input({ type: "text" });
    }
}
export class PercentEditor extends CellEditor {
    static __name__ = "PercentEditor";
    static {
        this.prototype.default_view = PercentEditorView;
    }
}
export class CheckboxEditorView extends CellEditorView {
    static __name__ = "CheckboxEditorView";
    _createInput() {
        return input({ type: "checkbox" });
    }
    renderEditor() {
        this.focus();
    }
    loadValue(item) {
        this.defaultValue = !!item[this.args.column.field];
        this.inputEl.checked = this.defaultValue;
    }
    serializeValue() {
        return this.inputEl.checked;
    }
}
export class CheckboxEditor extends CellEditor {
    static __name__ = "CheckboxEditor";
    static {
        this.prototype.default_view = CheckboxEditorView;
    }
}
export class IntEditorView extends CellEditorView {
    static __name__ = "IntEditorView";
    _createInput() {
        return input({ type: "text" });
    }
    renderEditor() {
        //$(@inputEl).spinner({step: @model.step})
        this.inputEl.focus();
        this.inputEl.select();
    }
    remove() {
        //$(@inputEl).spinner("destroy")
        super.remove();
    }
    serializeValue() {
        const value = parseInt(this.getValue(), 10);
        return isNaN(value) ? 0 : value;
    }
    loadValue(item) {
        super.loadValue(item);
        this.inputEl.defaultValue = this.defaultValue;
        this.inputEl.select();
    }
    validateValue(value) {
        if (isString(value)) {
            value = Number(value);
        }
        if (isInteger(value)) {
            return super.validateValue(value);
        }
        else {
            return { valid: false, msg: "Please enter a valid integer" };
        }
    }
}
export class IntEditor extends CellEditor {
    static __name__ = "IntEditor";
    static {
        this.prototype.default_view = IntEditorView;
        this.define(({ Int }) => ({
            step: [Int, 1],
        }));
    }
}
export class NumberEditorView extends CellEditorView {
    static __name__ = "NumberEditorView";
    _createInput() {
        return input({ type: "text" });
    }
    renderEditor() {
        //$(@inputEl).spinner({step: @model.step})
        this.inputEl.focus();
        this.inputEl.select();
    }
    remove() {
        //$(@inputEl).spinner("destroy")
        super.remove();
    }
    serializeValue() {
        const value = parseFloat(this.getValue());
        return isNaN(value) ? 0.0 : value;
    }
    loadValue(item) {
        super.loadValue(item);
        this.inputEl.defaultValue = this.defaultValue;
        this.inputEl.select();
    }
    validateValue(value) {
        if (isNaN(value)) {
            return { valid: false, msg: "Please enter a valid number" };
        }
        else {
            return super.validateValue(value);
        }
    }
}
export class NumberEditor extends CellEditor {
    static __name__ = "NumberEditor";
    static {
        this.prototype.default_view = NumberEditorView;
        this.define(({ Float }) => ({
            step: [Float, 0.01],
        }));
    }
}
export class TimeEditorView extends CellEditorView {
    static __name__ = "TimeEditorView";
    _createInput() {
        return input({ type: "text" });
    }
}
export class TimeEditor extends CellEditor {
    static __name__ = "TimeEditor";
    static {
        this.prototype.default_view = TimeEditorView;
    }
}
export class DateEditorView extends CellEditorView {
    static __name__ = "DateEditorView";
    _createInput() {
        return input({ type: "text" });
    }
    get emptyValue() {
        return new Date();
    }
    renderEditor() {
        //this.calendarOpen = false
        //@$datepicker = $(@inputEl).datepicker({
        //  showOn: "button"
        //  buttonImageOnly: true
        //  beforeShow: () => @calendarOpen = true
        //  onClose: () => @calendarOpen = false
        //})
        //@$datepicker.siblings(".ui-datepicker-trigger").css("vertical-align": "middle")
        //@$datepicker.width(@$datepicker.width() - (14 + 2*4 + 4)) # img width + margins + edge distance
        this.inputEl.focus();
        this.inputEl.select();
    }
    destroy() {
        //$.datepicker.dpDiv.stop(true, true)
        //@$datepicker.datepicker("hide")
        //@$datepicker.datepicker("destroy")
        super.destroy();
    }
    show() {
        //if @calendarOpen
        //  $.datepicker.dpDiv.stop(true, true).show()
        super.show();
    }
    hide() {
        //if @calendarOpen
        //  $.datepicker.dpDiv.stop(true, true).hide()
        super.hide();
    }
    position( /*_position*/) {
        //if @calendarOpen
        //  $.datepicker.dpDiv.css(top: position.top + 30, left: position.left)
        return super.position();
    }
    getValue() {
        //return @$datepicker.datepicker("getDate").getTime()
    }
    setValue(_val) {
        //@$datepicker.datepicker("setDate", new Date(val))
    }
}
export class DateEditor extends CellEditor {
    static __name__ = "DateEditor";
    static {
        this.prototype.default_view = DateEditorView;
    }
}
//# sourceMappingURL=cell_editors.js.map