package com.ecep.contract.controller.company;

import java.lang.reflect.InvocationTargetException;
import java.time.format.DateTimeFormatter;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

import com.ecep.contract.controller.BaseController;
import com.ecep.contract.model.CompanyContact;
import com.ecep.contract.service.CompanyContactService;
import com.ecep.contract.util.FxmlUtils;
import com.ecep.contract.util.UITools;
import com.ecep.contract.vm.CompanyContactViewModel;

import javafx.application.Platform;
import javafx.scene.control.Button;
import javafx.scene.control.DatePicker;
import javafx.scene.control.Label;
import javafx.scene.control.Tab;
import javafx.scene.control.TabPane;
import javafx.scene.control.TextArea;
import javafx.scene.control.TextField;
import javafx.scene.layout.BorderPane;
import javafx.stage.Modality;
import javafx.stage.Stage;
import javafx.stage.Window;
import javafx.stage.WindowEvent;
import javafx.util.converter.LocalDateStringConverter;
import lombok.Getter;
import lombok.Setter;

@Lazy
@Scope("prototype")
@Component
public class CompanyContactWindowController extends BaseController {
    private static final Logger logger = LoggerFactory.getLogger(CompanyContactWindowController.class);

    /**
     * 显示界面
     */
    public static void show(CompanyContactViewModel viewModel, Window window) {
        String key = toKey(viewModel);
        // 一个合同一个界面
        if (toFront(key)) {
            return;
        }
        FxmlUtils.newLoaderAsyncWithRunLater("/ui/contact.fxml", null, loader -> {
            CompanyContactWindowController controller = loader.getController();
            controller.setViewModel(viewModel);
            controller.show(loader, window, Modality.NONE, key);
        });
    }

    private static String toKey(CompanyContactViewModel viewModel) {
        return viewModel.getClass().getName() + "-" + viewModel.getId().get();
    }

    public Tab baseInfoTab;
    public BorderPane root;
    public TabPane tabPane;

    @Getter
    @Setter
    private CompanyContactViewModel viewModel;

    @Autowired
    private CompanyContactService companyContactService;

    public TextField nameField;
    public TextField positionField;
    public TextField phoneField;
    public DatePicker createdField;
    public TextField u8CodeField;
    public TextField emailField;
    public TextField addressField;
    public TextArea descriptionField;
    public Label versionLabel;
    public Button saveBtn;

    private CompletableFuture<CompanyContact> companyContactLoadedFuture;

    @Override
    public void show(Stage stage) {
        super.show(stage);
        getTitle().bind(viewModel.getName()
                .map(v -> "[" + viewModel.getId().get() + "] " + viewModel.getName().getValue() + " 曾用名详情"));
    }

    @Override
    public void onShown(WindowEvent windowEvent) {
        super.onShown(windowEvent);
        if (logger.isDebugEnabled()) {
            logger.debug("onShown");
        }

        initializeBaseTab();

        companyContactLoadedFuture = CompletableFuture.supplyAsync(() -> {
            CompanyContact oldName = companyContactService.findById(viewModel.getId().get());
            Platform.runLater(() -> {
                viewModel.update(oldName);
                viewModel.bindListener();
                if (logger.isDebugEnabled()) {
                    logger.debug("bind ViewModel({}) Listener", viewModel.getName().get());
                }
                tabPane.getSelectionModel().getSelectedItem().getOnSelectionChanged().handle(null);
            });
            return oldName;
        });
    }

    private void initializeBaseTab() {
        baseInfoTab.setOnSelectionChanged(event -> {
            if (logger.isDebugEnabled()) {
                logger.debug("baseInfoTab OnSelectionChanged");
            }
            if (baseInfoTab.isSelected()) {
                onBaseTabShown();
            }
        });
        saveBtn.disableProperty().bind(viewModel.getChanged().not());
        saveBtn.setOnAction(event -> {
            try {
                CompanyContact contact = companyContactLoadedFuture.join();
                viewModel.copyTo(contact);
                CompanyContact saved = companyContactService.save(contact);
                viewModel.update(saved);
                companyContactLoadedFuture = CompletableFuture.completedFuture(saved);
            } catch (Exception e) {
                UITools.showExceptionAndWait("保存失败,请检查", e);
            }
        });

        nameField.textProperty().bindBidirectional(viewModel.getName());
        positionField.textProperty().bindBidirectional(viewModel.getPosition());
        phoneField.textProperty().bindBidirectional(viewModel.getPhone());
        emailField.textProperty().bindBidirectional(viewModel.getEmail());
        addressField.textProperty().bindBidirectional(viewModel.getAddress());
        LocalDateStringConverter converter = new LocalDateStringConverter(DateTimeFormatter.ISO_LOCAL_DATE, null);
        createdField.setConverter(converter);
        createdField.valueProperty().bindBidirectional(viewModel.getCreated());
        u8CodeField.textProperty().bind(viewModel.getU8Code());
        descriptionField.textProperty().bindBidirectional(viewModel.getMemo());
        versionLabel.textProperty().bind(viewModel.getVersion().asString());
    }

    /**
     * 基础页显示时回调函数
     */
    private void onBaseTabShown() {
        if (logger.isDebugEnabled()) {
            logger.debug("onBaseTabShown");
        }
        companyContactLoadedFuture.thenAcceptAsync(contact -> {
            if (logger.isDebugEnabled()) {
                logger.debug("onBaseTabShown company contact {}", contact.getName());
            }
            // viewModel.update(contact);
        }).exceptionally(ex -> {
            UITools.showExceptionAndWait(ex.getMessage(), ex);
            return null;
        });
    }

    public void onHidden(WindowEvent windowEvent) {
        if (viewModel != null) {
            try {
                viewModel.unBindListener();
                if (logger.isDebugEnabled()) {
                    logger.debug("unbind ViewModel({}) Listener", viewModel.getName().get());
                }
            } catch (InvocationTargetException | IllegalAccessException e) {
                throw new RuntimeException(e);
            }
        }
        super.onHidden(windowEvent);
    }
}
