package com.ecep.contract.controller.project;

import java.util.Map;

import com.ecep.contract.controller.AbstEntityManagerSkin;
import com.ecep.contract.controller.BaseController;
import com.ecep.contract.controller.ComboBoxUtils;
import com.ecep.contract.controller.ManagerSkin;
import com.ecep.contract.controller.table.cell.CompanyTableCell;
import com.ecep.contract.converter.EntityStringConverter;
import com.ecep.contract.model.Company;
import com.ecep.contract.model.ProductType;
import com.ecep.contract.model.Project;
import com.ecep.contract.model.ProjectSaleType;
import com.ecep.contract.model.ProjectType;
import com.ecep.contract.service.CompanyService;
import com.ecep.contract.service.ProductTypeService;
import com.ecep.contract.service.ProjectService;
import com.ecep.contract.service.ProjectTypeService;
import com.ecep.contract.service.SaleTypeService;
import com.ecep.contract.vm.ProjectViewModel;

import javafx.application.Platform;
import javafx.event.ActionEvent;
import javafx.scene.control.TableColumn;
import javafx.scene.control.cell.CheckBoxTableCell;
import javafx.scene.control.cell.TextFieldTableCell;
import javafx.util.converter.CurrencyStringConverter;
import lombok.Setter;

public class ProjectManagerSkin
        extends AbstEntityManagerSkin<Project, ProjectViewModel, ProjectManagerSkin, ProjectManagerWindowController>
        implements ManagerSkin {
    @Setter
    private CompanyService companyService;
    @Setter
    private ProjectTypeService projectTypeService;
    @Setter
    private SaleTypeService saleTypeService;
    @Setter
    private ProductTypeService productTypeService;

    public ProjectManagerSkin(ProjectManagerWindowController controller) {
        super(controller);
    }

    public ProjectService getProjectService() {
        return controller.getViewModelService();
    }

    public CompanyService getCompanyService() {
        if (companyService == null) {
            companyService = getBean(CompanyService.class);
        }
        return companyService;
    }

    public SaleTypeService getSaleTypeService() {
        if (saleTypeService == null) {
            saleTypeService = getBean(SaleTypeService.class);
        }
        return saleTypeService;
    }

    public ProjectTypeService getProjectTypeService() {
        if (projectTypeService == null) {
            projectTypeService = getBean(ProjectTypeService.class);
        }
        return projectTypeService;
    }

    public ProductTypeService getProductTypeService() {
        if (productTypeService == null) {
            productTypeService = getBean(ProductTypeService.class);
        }
        return productTypeService;
    }

    @Override
    public Map<String, Object> getSpecification() {
        Map<String, Object> params = super.getSpecification();
        if (controller.saleTypeSelector.getValue() != null) {
            params.put("saleType", controller.saleTypeSelector.getValue());
        }
        return params;
    }

    @Override
    public void initializeTable() {
        ComboBoxUtils.initialComboBox(controller.saleTypeSelector, getSaleTypeService().findAll(), true);
        controller.saleTypeSelector.valueProperty().addListener((observable, oldValue, newValue) -> {
            loadTableDataSet(false);
        });

        controller.idColumn.setCellValueFactory(param -> param.getValue().getId());
        controller.codeColumn.setCellValueFactory(param -> param.getValue().getCode());
        controller.nameColumn.setCellValueFactory(param -> param.getValue().getName());

        controller.amountColumn.setCellValueFactory(param -> param.getValue().getAmount());
        controller.amountColumn
                .setCellFactory(TextFieldTableCell.forTableColumn(new CurrencyStringConverter(getLocale())));// ,
                                                                                                             // "#,##0"

        initializeSaleTypeColumn(controller.saleTypeColumn);
        initializeCustomerColumn(controller.customerColumn);
        initializeProjectTypeColumn(controller.projectTypeColumn);
        initializeProductTypeColumn(controller.productTypeColumn);

        controller.useBidColumn.setCellValueFactory(param -> param.getValue().getUseBid());
        controller.useBidColumn.setCellFactory(CheckBoxTableCell.forTableColumn(controller.useBidColumn));
        controller.useOfferColumn.setCellValueFactory(param -> param.getValue().getUseOffer());
        controller.useOfferColumn.setCellFactory(CheckBoxTableCell.forTableColumn(controller.useOfferColumn));

        controller.createdColumn.setCellValueFactory(param -> param.getValue().getCreated());

        Platform.runLater(() -> {
            getTableView().getSortOrder().add(controller.idColumn);
        });
    }

    private void initializeCustomerColumn(TableColumn<ProjectViewModel, Company> column) {
        column.setCellValueFactory(param -> param.getValue().getCustomer());
        column.setCellFactory(param -> new CompanyTableCell<>(getCompanyService()));
    }

    private void initializeProductTypeColumn(TableColumn<ProjectViewModel, String> column) {
        EntityStringConverter<ProductType> converter = new EntityStringConverter<>();
        converter.setInitialized(productType -> getProductTypeService().findById(productType.getId()));
        converter.setFromString(name -> getProductTypeService().findByName(name));
        column.setCellValueFactory(param -> param.getValue().getProductType().map(converter::toString));
    }

    private void initializeProjectTypeColumn(TableColumn<ProjectViewModel, String> column) {
        EntityStringConverter<ProjectType> converter = new EntityStringConverter<>();
        converter.setInitialized(projectType -> getProjectTypeService().findById(projectType.getId()));
        converter.setFromString(name -> getProjectTypeService().findByName(name));
        column.setCellValueFactory(param -> param.getValue().getProjectType().map(converter::toString));
    }

    private void initializeSaleTypeColumn(TableColumn<ProjectViewModel, String> column) {
        EntityStringConverter<ProjectSaleType> converter = new EntityStringConverter<>();
        converter.setInitialized(saleType -> getSaleTypeService().findById(saleType.getId()));
        converter.setFromString(name -> getSaleTypeService().findByName(name));
        column.setCellValueFactory(param -> param.getValue().getSaleType().map(converter::toString));
    }

    @Override
    protected void onTableRowDoubleClickedAction(ProjectViewModel item) {
        showInOwner(item);
    }

    @Override
    protected void onTableCreateNewAction(ActionEvent event) {
        BaseController.show(ApplyNewProjectWindowController.class, getTableView().getScene().getWindow(),
                controller -> {
                    controller.setOnApplied(project -> {
                        ProjectViewModel viewModel = ProjectViewModel.from(project);
                        dataSet.addFirst(viewModel);
                        showInOwner(viewModel);
                    });
                });
    }

    private void showInOwner(ProjectViewModel model) {
        showInOwner(ProjectWindowController.class, model);
    }
}
