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

import java.util.concurrent.Future;

import com.ecep.contract.util.ProxyUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.ecep.contract.Desktop;
import com.ecep.contract.model.BasedEntity;
import com.ecep.contract.model.IdentityEntity;
import com.ecep.contract.model.NamedEntity;
import com.ecep.contract.service.IEntityService;

import javafx.application.Platform;

/**
 * 异步更新表格, 当单元格对应的数据未被初始化时, 显示#id, 当初始化后, 显示对应的文本
 * 
 * @param <V>
 * @param <T>
 */
public class AsyncUpdateTableCell<V, T extends IdentityEntity> extends javafx.scene.control.TableCell<V, T> {
    private static final Logger logger = LoggerFactory.getLogger(AsyncUpdateTableCell.class);

    /**
     * 转换为文本
     */
    public static String toString(Object entity) {
        if (entity instanceof NamedEntity named) {
            return named.getName();
        }
        if (entity instanceof BasedEntity e) {
            return e.toPrettyString();
        }
        return entity.toString();
    }

    private IEntityService<T> service;
    Future<?> syncFuture;

    /**
     * 通过 #setService 设置服务类，或者子类实现, 提供服务类
     * 
     * @return
     */
    protected IEntityService<T> getServiceBean() {
        return null;
    }

    public String format(T entity) {
        return toString(entity);
    }

    public void setService(IEntityService<T> service) {
        this.service = service;
    }

    public IEntityService<T> getService() {
        if (service == null) {
            service = getServiceBean();
        }
        return service;
    }

    @Override
    protected void updateItem(T item, boolean empty) {
        super.updateItem(item, empty);
        // 取消之前的异步任务
        if (syncFuture != null) {
            syncFuture.cancel(true);
            syncFuture = null;
        }

        if (empty || item == null) {
            setText(null);
            return;
        }
        if (isInitialized(item)) {
            setText(format(item));
            return;
        }

        setText("# " + item.getId());
        syncFuture = submit(this::asyncLoadAndUpdate);
    }

    /**
     * 检查实体是否已初始化
     * 
     * @param proxy
     * @return
     */
    protected boolean isInitialized(T proxy) {
        return ProxyUtils.isInitialized(proxy);
    }

    /**
     * 初始化实体
     * 
     * @return
     */
    protected T initialize() {
        return getService().findById(getItem().getId());
    }

    /**
     * 提交异步任务
     * 
     * @param var1 异步任务
     * @return
     */
    Future<?> submit(Runnable var1) {
        return Desktop.instance.getExecutorService().submit(var1);
    }

    protected void asyncLoadAndUpdate() {
        if (getItem() == null) {
            return;
        }

        T entity = initialize();
        String formated;
        try {
            formated = format(entity);
        } catch (Exception e) {
            formated = e.getMessage();
        }
        String texted = formated;

        // 保存当前需要更新的项目信息，避免闭包引用导致的问题
        final T updatedEntity = entity;
        final String updatedText = texted;
        final T finalCurrentLoadingItem = getItem();

        Platform.runLater(() -> {
            // 检查单元格是否仍然显示相同的项目
            // 如果单元格已被重用或当前项目已改变，则不更新
            if (isEmpty() || getItem() == null) {
                logger.debug("Skipping async update - cell reused ");
                return;
            }
            if (getItem().getId() != finalCurrentLoadingItem.getId()) {
                logger.debug("Skipping async update - cell item changed");
                return;
            }
            setItem(updatedEntity);
            setText(updatedText);
        });
    }

}
