package com.ecep.contract.controller.tab;

import java.io.File;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.concurrent.CompletableFuture;

import org.springframework.util.StringUtils;

import com.ecep.contract.DesktopUtils;
import com.ecep.contract.controller.company.AbstCompanyTableTabSkin;
import com.ecep.contract.controller.company.CompanyWindowController;
import com.ecep.contract.controller.contract.ContractWindowController;
import com.ecep.contract.controller.table.EditableEntityTableTabSkin;
import com.ecep.contract.controller.table.cell.ContractGroupTableCell;
import com.ecep.contract.controller.table.cell.ContractKindTableCell;
import com.ecep.contract.controller.table.cell.ContractTypeTableCell;
import com.ecep.contract.controller.table.cell.EmployeeTableCell;
import com.ecep.contract.controller.table.cell.LocalDateTimeTableCell;
import com.ecep.contract.converter.ContractGroupStringConverter;
import com.ecep.contract.model.Company;
import com.ecep.contract.model.Contract;
import com.ecep.contract.model.ContractGroup;
import com.ecep.contract.model.ContractKind;
import com.ecep.contract.model.ContractType;
import com.ecep.contract.model.Employee;
import com.ecep.contract.service.ContractGroupService;
import com.ecep.contract.service.ContractKindService;
import com.ecep.contract.service.ContractService;
import com.ecep.contract.service.ContractTypeService;
import com.ecep.contract.task.ContractRepairByCompanyTask;
import com.ecep.contract.util.FxmlPath;
import com.ecep.contract.util.UITools;
import com.ecep.contract.vm.ContractViewModel;

import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.scene.control.Button;
import javafx.scene.control.ComboBox;
import javafx.scene.control.MenuItem;
import javafx.scene.control.Tab;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TextField;
import javafx.scene.input.KeyCode;

/**
 * 子合同
 */
@FxmlPath("/ui/company/company-tab-contract.fxml")
public class CompanyTabSkinContract
        extends AbstCompanyTableTabSkin<Contract, ContractViewModel>
        implements TabSkin, EditableEntityTableTabSkin<Contract, ContractViewModel> {

    public TableColumn<ContractViewModel, Number> contractTable_idColumn;
    public TableColumn<ContractViewModel, String> contractTable_codeColumn;
    public TableColumn<ContractViewModel, String> contractTable_nameColumn;
    public TableColumn<ContractViewModel, String> contractTable_stateColumn;
    public TableColumn<ContractViewModel, ContractGroup> contractTable_groupColumn;
    public TableColumn<ContractViewModel, ContractType> contractTable_typeColumn;
    public TableColumn<ContractViewModel, ContractKind> contractTable_kindColumn;
    public TableColumn<ContractViewModel, String> contractTable_parentCodeColumn;
    public TableColumn<ContractViewModel, LocalDate> contractTable_orderDateColumn;
    public TableColumn<ContractViewModel, LocalDate> contractTable_startDateColumn;
    public TableColumn<ContractViewModel, LocalDate> contractTable_endDateColumn;
    public TableColumn<ContractViewModel, Employee> contractTable_setupPersonColumn;
    public TableColumn<ContractViewModel, LocalDate> contractTable_setupDateColumn;
    public TableColumn<ContractViewModel, Employee> contractTable_inurePersonColumn;
    public TableColumn<ContractViewModel, LocalDate> contractTable_inureDateColumn;
    public TableColumn<ContractViewModel, Employee> contractTable_varyPersonColumn;
    public TableColumn<ContractViewModel, LocalDate> contractTable_varyDateColumn;
    public TableColumn<ContractViewModel, LocalDateTime> contractTable_createdColumn;

    public ComboBox<ContractGroup> contractGroupSelector;
    public TextField contractSearchKeyField;
    public Button contractSearchBtn;
    public Button contractTabToolBtn1;
    public MenuItem contractTable_menu_refresh;
    public MenuItem contractTable_menu_add;
    public MenuItem contractTable_menu_open_in_explorer;
    public MenuItem contractTable_menu_update;
    public MenuItem contractTable_menu_del;

    public CompanyTabSkinContract(CompanyWindowController controller) {
        super(controller);
    }

    @Override
    public Tab getTab() {
        return controller.contractTab;
    }

    @Override
    public Map<String, Object> getSpecification(Company parent) {
        Map<String, Object> spec = super.getSpecification(parent);
        ContractGroup selectedGroup = contractGroupSelector.getValue();
        if (selectedGroup != null) {
            spec.put("group", selectedGroup.getId());
        }
        return spec;
    }

    @Override
    public void initializeTab() {
        contractSearchKeyField.setOnKeyReleased(event -> {
            if (event.getCode() == KeyCode.ENTER) {
                contractSearchBtn.fire();
            }
        });

        contractSearchBtn.setOnAction(this::onTableRefreshAction);

        ObservableList<ContractGroup> contractGroups = FXCollections.observableArrayList();
        contractGroups.add(null);
        contractGroups.addAll(getContractGroupService().findAll());
        contractGroupSelector.setItems(contractGroups);
        contractGroupSelector.setConverter(new ContractGroupStringConverter(contractGroups));
        contractSearchKeyField.setOnKeyReleased(event -> {
            if (event.getCode() == KeyCode.ENTER) {
                contractSearchBtn.fire();
            }
        });

        contractTabToolBtn1.setOnAction(event -> {
            CompletableFuture.runAsync(() -> {
                // 计算主合同编号
                for (ContractViewModel model : dataSet) {
                    Contract contract = getViewModelService().findById(model.getId().get());
                    if (contract == null) {
                        continue;
                    }
                    try {
                        if (getViewModelService().updateParentCode(contract)) {
                            Contract updated = getViewModelService().save(contract);
                            model.update(updated);
                        }
                    } catch (NoSuchElementException e) {
                        model.getParentCode().set(e.getMessage());
                    }
                }
            });
        });

        contractTable_idColumn.setCellValueFactory(param -> param.getValue().getId());
        contractTable_codeColumn.setCellValueFactory(param -> param.getValue().getCode());
        contractTable_nameColumn.setCellValueFactory(param -> param.getValue().getName());
        contractTable_stateColumn.setCellValueFactory(param -> param.getValue().getState());
        contractTable_groupColumn.setCellValueFactory(param -> param.getValue().getGroup());
        contractTable_groupColumn.setCellFactory(param -> new ContractGroupTableCell<>(getContractGroupService()));

        contractTable_typeColumn.setCellValueFactory(param -> param.getValue().getType());
        contractTable_typeColumn.setCellFactory(param -> new ContractTypeTableCell<>(getContractTypeService()));

        contractTable_kindColumn.setCellValueFactory(param -> param.getValue().getKind());
        contractTable_kindColumn.setCellFactory(param -> new ContractKindTableCell<>(getContractKindService()));

        contractTable_parentCodeColumn.setCellValueFactory(param -> param.getValue().getParentCode());
        contractTable_orderDateColumn.setCellValueFactory(param -> param.getValue().getOrderDate());
        contractTable_startDateColumn.setCellValueFactory(param -> param.getValue().getStartDate());
        contractTable_endDateColumn.setCellValueFactory(param -> param.getValue().getEndDate());
        contractTable_setupPersonColumn.setCellValueFactory(param -> param.getValue().getSetupPerson());
        contractTable_setupPersonColumn.setCellFactory(param -> new EmployeeTableCell<>(getEmployeeService()));

        contractTable_setupDateColumn.setCellValueFactory(param -> param.getValue().getSetupDate());
        // contractTable_setupDateColumn.setSortable(true);
        // contractTable_setupDateColumn.setSortType(TableColumn.SortType.DESCENDING);
        contractTable_inurePersonColumn.setCellValueFactory(param -> param.getValue().getInurePerson());
        contractTable_inurePersonColumn.setCellFactory(param -> new EmployeeTableCell<>(getEmployeeService()));

        contractTable_inureDateColumn.setCellValueFactory(param -> param.getValue().getInureDate());

        contractTable_varyPersonColumn.setCellValueFactory(param -> param.getValue().getVaryPerson());
        contractTable_varyPersonColumn.setCellFactory(param -> new EmployeeTableCell<>(getEmployeeService()));

        contractTable_varyDateColumn.setCellValueFactory(param -> param.getValue().getVaryDate());
        contractTable_createdColumn.setCellValueFactory(param -> param.getValue().getCreated());
        contractTable_createdColumn.setCellFactory(param -> new LocalDateTimeTableCell<>());

        contractTable_menu_refresh.setOnAction(this::onTableRefreshAction);
        // contractTable_menu_add.setOnAction(this::onTableAddAction);
        contractTable_menu_del.setOnAction(this::onTableDeleteAction);
        contractTable_menu_open_in_explorer.setOnAction(this::onTableOpenInExplorerAction);
        contractTable_menu_update.setOnAction(this::onTableUpdateAction);

        super.initializeTab();
    }

    private void onTableUpdateAction(ActionEvent event) {
        ContractRepairByCompanyTask task = new ContractRepairByCompanyTask();
        task.setCompany(getParent());
        UITools.showTaskDialogAndWait("同步合同", task, null);
        if (task.isRepaired()) {
            loadTableDataSet();
        }
    }

    private void onTableOpenInExplorerAction(ActionEvent event) {
        ContractViewModel selectedItem = getSelectedItem();
        if (selectedItem != null) {
            showInExplorer(selectedItem.getPath().get());
        }
    }

    private void showInExplorer(String path) {
        if (!StringUtils.hasText(path)) {
            setStatus("文件/目录为空，无法打开");
            return;
        }
        File file = new File(path);
        if (!file.exists()) {
            if (file.isFile()) {
                setStatus("文件 " + file.getAbsolutePath() + " 不存在，请确认");
            } else {
                setStatus("目录 " + file.getAbsolutePath() + " 不存在，请确认");
            }
            return;
        }

        try {
            DesktopUtils.showInExplorer(file);
            setStatus("打开文件/目录 " + path);
        } catch (Exception e) {
            setStatus("打开文件错误：" + e.getMessage());
        }
    }

    @Override
    protected void onTableRowDoubleClickedAction(ContractViewModel item) {
        ContractWindowController.show(item, controller.root.getScene().getWindow());
    }

    protected ContractService getViewModelService() {
        return getCachedBean(ContractService.class);
    }

    private ContractTypeService getContractTypeService() {
        return getCachedBean(ContractTypeService.class);
    }

    private ContractKindService getContractKindService() {
        return getCachedBean(ContractKindService.class);
    }

    private ContractGroupService getContractGroupService() {
        return getCachedBean(ContractGroupService.class);
    }
}
