package com.ecep.contract.controller.project.sale_type;

import java.util.List;
import java.util.Map;

import org.springframework.data.domain.Page;

import com.ecep.contract.controller.AbstEntityManagerSkin;
import com.ecep.contract.controller.ManagerSkin;
import com.ecep.contract.controller.table.EditableEntityTableTabSkin;
import com.ecep.contract.model.ProjectSaleType;
import com.ecep.contract.service.SaleTypeService;
import com.ecep.contract.service.ViewModelService;
import com.ecep.contract.vm.ProjectSaleTypeViewModel;

import javafx.scene.control.TableColumn;
import javafx.scene.control.cell.CheckBoxTableCell;
import javafx.scene.control.cell.TextFieldTableCell;
import lombok.Setter;

public class ProjectSaleTypeManagerSkin
        extends
        AbstEntityManagerSkin<ProjectSaleType, ProjectSaleTypeViewModel, ProjectSaleTypeManagerSkin, ProjectSaleTypeManagerWindowController>
        implements ManagerSkin, EditableEntityTableTabSkin<ProjectSaleType, ProjectSaleTypeViewModel> {

    @Setter
    private SaleTypeService saleTypeService;

    public ProjectSaleTypeManagerSkin(ProjectSaleTypeManagerWindowController controller) {
        super(controller);
    }

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

    @Override
    public void initializeTable() {
        initializeSaleTypeTable();
    }

    @Override
    protected List<ProjectSaleTypeViewModel> loadTableData() {
        Map<String, Object> params = getSpecification();
        ViewModelService<ProjectSaleType, ProjectSaleTypeViewModel> service = getViewModelService();
        Page<ProjectSaleType> page = service.findAll(params, getPageable());
        updateFooter(page);
        return page.map(service::from).stream().peek(v -> {
            v.getStoreByYear().addListener((observable, oldValue, newValue) -> saveRowData(v));
            v.getActive().addListener((observable, oldValue, newValue) -> saveRowData(v));
        }).toList();
    }

    private void initializeSaleTypeTable() {
        controller.idColumn.setCellValueFactory(param -> param.getValue().getId());
        controller.idColumn.setEditable(false);

        controller.codeColumn.setCellValueFactory(param -> param.getValue().getCode());
        controller.codeColumn.setEditable(false);
        controller.codeColumn.setCellFactory(TextFieldTableCell.forTableColumn());
        controller.codeColumn.setOnEditCommit(this::onCodeColumnEditCommitAction);

        controller.nameColumn.setCellValueFactory(param -> param.getValue().getName());
        controller.nameColumn.setEditable(false);
        controller.nameColumn.setCellFactory(TextFieldTableCell.forTableColumn());
        controller.nameColumn.setOnEditCommit(this::onNameColumnEditCommitAction);

        controller.pathColumn.setCellValueFactory(param -> param.getValue().getPath());
        controller.pathColumn.setEditable(false);
        controller.pathColumn.setCellFactory(TextFieldTableCell.forTableColumn());
        controller.pathColumn.setOnEditCommit(this::onPathColumnEditCommitAction);

        controller.storeByYearColumn.setCellValueFactory(param -> param.getValue().getStoreByYear());
        controller.storeByYearColumn.setEditable(false);
        controller.storeByYearColumn.setCellFactory(CheckBoxTableCell.forTableColumn(controller.storeByYearColumn));
        controller.storeByYearColumn.setOnEditCommit(this::onStoreByYearColumnEditCommitAction);

        controller.descriptionColumn.setCellValueFactory(param -> param.getValue().getDescription());
        controller.descriptionColumn.setEditable(false);
        controller.descriptionColumn.setCellFactory(TextFieldTableCell.forTableColumn());
        controller.descriptionColumn.setOnEditCommit(this::onDescriptionColumnEditCommitAction);

        controller.activeColumn.setCellValueFactory(param -> param.getValue().getActive());
        controller.activeColumn.setCellFactory(CheckBoxTableCell.forTableColumn(controller.activeColumn));
        controller.activeColumn.setOnEditCommit(this::onActiveColumnEditCommitAction);

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

    @Override
    public ProjectSaleType loadRowData(ProjectSaleTypeViewModel row) {
        ProjectSaleType type = super.loadRowData(row);
        if (type == null) {
            type = new ProjectSaleType();
            type.setCode("-");
        }
        return type;
    }

    private void onDescriptionColumnEditCommitAction(
            TableColumn.CellEditEvent<ProjectSaleTypeViewModel, String> event) {
        acceptCellEditEvent(event, ProjectSaleTypeViewModel::getDescription);
    }

    private void onNameColumnEditCommitAction(TableColumn.CellEditEvent<ProjectSaleTypeViewModel, String> event) {
        acceptCellEditEvent(event, ProjectSaleTypeViewModel::getName);
    }

    private void onCodeColumnEditCommitAction(TableColumn.CellEditEvent<ProjectSaleTypeViewModel, String> event) {
        acceptCellEditEvent(event, ProjectSaleTypeViewModel::getCode);
    }

    private void onPathColumnEditCommitAction(TableColumn.CellEditEvent<ProjectSaleTypeViewModel, String> event) {
        acceptCellEditEvent(event, ProjectSaleTypeViewModel::getPath);
    }

    private void onStoreByYearColumnEditCommitAction(
            TableColumn.CellEditEvent<ProjectSaleTypeViewModel, Boolean> event) {
        acceptCellEditEvent(event, ProjectSaleTypeViewModel::getStoreByYear);
    }

    private void onActiveColumnEditCommitAction(TableColumn.CellEditEvent<ProjectSaleTypeViewModel, Boolean> event) {
        acceptCellEditEvent(event, ProjectSaleTypeViewModel::getActive);
    }

    @Override
    protected void onTableRowDoubleClickedAction(ProjectSaleTypeViewModel item) {
        showInOwner(ProjectSaleTypeWindowController.class, item);
    }
}
