package com.ecep.contract.controller.table.cell;

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;

import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.scene.control.DatePicker;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.input.KeyCode;
import javafx.util.Callback;
import javafx.util.StringConverter;
import javafx.util.converter.LocalDateStringConverter;

/**
 * TableView 的日期单元格编辑器
 * <p>
 * 使用 DatePicker 作为日期选择控件
 *
 * @param <S>
 */
public class LocalDateFieldTableCell<S> extends TableCell<S, LocalDate> {


    public static <S> Callback<TableColumn<S, LocalDate>, TableCell<S, LocalDate>> forTableColumn() {
        return forTableColumn(new DatePicker());
    }

    public static <S> Callback<TableColumn<S, LocalDate>, TableCell<S, LocalDate>> forTableColumn(DatePicker datePicker) {
        return list -> new LocalDateFieldTableCell<>(datePicker);
    }

    private final DatePicker datePicker;


    public LocalDateFieldTableCell(DatePicker datePicker) {
        this.datePicker = datePicker;
        // 设置 DatePicker 的初始值
        datePicker.setValue(null);

        // 当 DatePicker 的值发生变化时，更新单元格的值
        datePicker.valueProperty().addListener((obs, oldValue, newValue) -> {
            if (isEditing()) {
                commitEdit(newValue);
            }
        });
        // 监听键盘事件，按下 Enter 键提交编辑
        datePicker.setOnKeyPressed(event -> {
            if (event.getCode() == KeyCode.ENTER) {
                commitEdit(datePicker.getValue());
            }
        });

        // 当 DatePicker 失去焦点时，提交编辑
        datePicker.focusedProperty().addListener((obs, wasFocused, isNowFocused) -> {
            if (!isNowFocused) {
                commitEdit(datePicker.getValue());
            }
        });
    }

    private ObjectProperty<StringConverter<LocalDate>> converter =
            new SimpleObjectProperty<>(this, "converter");

    public final ObjectProperty<StringConverter<LocalDate>> converterProperty() {
        return converter;
    }

    /**
     * Sets the {@link StringConverter} to be used in this cell.
     *
     * @param value the {@link StringConverter} toLocalDate be used in this cell
     */
    public final void setConverter(StringConverter<LocalDate> value) {
        converterProperty().set(value);
    }

    /**
     * Returns the {@link StringConverter} used in this cell.
     *
     * @return the {@link StringConverter} used in this cell
     */
    public final StringConverter<LocalDate> getConverter() {
        StringConverter<LocalDate> stringConverter = converterProperty().get();
        if (stringConverter == null) {
            stringConverter = new LocalDateStringConverter(DateTimeFormatter.ISO_LOCAL_DATE, null);
            setConverter(stringConverter);
        }
        return stringConverter;
    }

    @Override
    public void startEdit() {
        if (isEmpty()) {
            return;
        }
        super.startEdit();
        setGraphic(datePicker);
        datePicker.setConverter(getConverter());
        datePicker.setValue(getItem());
        // 自动聚焦‌
        datePicker.requestFocus();
    }

    @Override
    public void cancelEdit() {
        super.cancelEdit();
        LocalDate item = getItem();
        if (item == null) {
            setText(null);
        } else {
            setText(getConverter().toString(item));
        }
        setGraphic(null);
    }

    @Override
    protected void updateItem(LocalDate item, boolean empty) {
        super.updateItem(item, empty);
        if (empty || item == null) {
            setText(null);
            setGraphic(null);
        } else {
            if (isEditing()) {
                datePicker.setValue(item);
                setGraphic(datePicker);
                setText(null);
            } else {
                setText(getConverter().toString(item));
                setGraphic(null);
            }
        }
    }
}
