package danielcortes.xyz.controllers;

import danielcortes.xyz.controllers.actions.MoveToAction;
import danielcortes.xyz.data.Configuration;
import danielcortes.xyz.data.DAOManager;
import danielcortes.xyz.models.caja.Caja;
import danielcortes.xyz.models.calculo_fondo.CalculoFondo;
import danielcortes.xyz.views.CalcularFondoView;
import danielcortes.xyz.views.components.table_model.FondoTableModel;

import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;

public class CalcularFondoController {
    private JComponent parent;
    private CalcularFondoView view;
    private Caja caja;

    private int editingId;
    private boolean editing;
    private CalculoFondo editingCalculoFondo;

    public CalcularFondoController(JComponent parent, CalcularFondoView view, Caja caja) {
        this.view = view;
        this.parent = parent;
        this.caja = caja;

        this.fillTable();
        this.updateResumen();
        this.setupViewEvents();
        this.updateButtonsEnabled();
        this.showView();
    }

    private void showView() {
        JFrame frame = new JFrame("Calculo de Fondo: " + Configuration.get("nombre_caja"));
        frame.setContentPane(view.getContentPanel());
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        frame.pack();
        frame.setLocationRelativeTo(this.parent);
        frame.setVisible(true);
    }

    private void fillTable() {
        FondoTableModel tableModel = this.view.getTableModel();
        tableModel.removeRows();
        for (CalculoFondo calculoFondo : DAOManager.getCalculoFondoDAO().findByCaja(this.caja)) {
            tableModel.addRow(calculoFondo);
        }
    }

    private void setupViewEvents() {
        this.view.getValorField().getInputMap(JComponent.WHEN_FOCUSED).put(KeyStroke.getKeyStroke("ENTER"), "nextField");
        this.view.getDescripcionField().getInputMap(JComponent.WHEN_FOCUSED).put(KeyStroke.getKeyStroke("ENTER"), "save");
        this.view.getFondoField().getInputMap(JComponent.WHEN_FOCUSED).put(KeyStroke.getKeyStroke("ENTER"), "updateResumen");

        this.view.getValorField().getActionMap().put("nextField", new MoveToAction(this.view.getDescripcionField()));
        this.view.getDescripcionField().getActionMap().put("save", new GuardarAction());
        this.view.getFondoField().getActionMap().put("updateResumen", new UpdateResumenAction());

        this.view.getTable().getSelectionModel().addListSelectionListener(e -> updateButtonsEnabled());

        this.view.getGuardarButton().addActionListener(e -> guardarActionListener());
        this.view.getEditarButton().addActionListener(e -> editarActionListener());
        this.view.getEliminarButton().addActionListener(e -> eliminarActionListener());

        this.view.getTable().addMouseListener(new MouseAdapter() {
            public void mouseClicked(MouseEvent mouseEvent) {
                JTable table = (JTable) mouseEvent.getSource();
                if (mouseEvent.getClickCount() == 2 && table.getSelectedRow() != -1) {
                    CalcularFondoController.this.editarActionListener();
                }
            }
        });
    }

    private void guardarActionListener() {
        this.normalizeInput();

        int valor = this.view.getValorField().getValue();
        String descripcion = this.view.getDescripcionField().getText();


        if (editing) {
            this.editarCalculoFondo(valor, descripcion);
            this.editing = false;
        } else {
            this.guardarCalculoFondo(valor, descripcion);
        }

        this.updateResumen();
        this.cleanInput();
        this.resetFocus();
    }

    private void editarActionListener() {
        int selectedID = this.view.getTable().getSelectedRow();
        if (selectedID >= 0) {
            int selectedModelID = this.view.getTable().getRowSorter().convertRowIndexToModel(selectedID);
            CalculoFondo calculoFondo = this.view.getTableModel().getCalculoFondo(selectedModelID);

            this.editingId = selectedModelID;
            this.editingCalculoFondo = calculoFondo;
            this.editing = true;

            this.view.getValorField().setValue(calculoFondo.getValor());
            this.view.getDescripcionField().setText(calculoFondo.getDescripcion());
        }
    }

    private void eliminarActionListener() {
        int selectedID = this.view.getTable().getSelectedRow();
        if (selectedID >= 0) {
            CalculoFondo calculoFondo = this.view.getTableModel().getCalculoFondo(selectedID);
            this.view.getTableModel().removeRow(selectedID);
            DAOManager.getCalculoFondoDAO().deleteCalculoFondo(calculoFondo);
            this.updateResumen();
            this.updateButtonsEnabled();
            this.resetFocus();
        }
    }

    private void guardarCalculoFondo(int valor, String descripcion) {
        CalculoFondo calculoFondo = new CalculoFondo();
        calculoFondo.setValor(valor);
        calculoFondo.setDescripcion(descripcion);
        calculoFondo.setCaja(this.caja);
        DAOManager.getCalculoFondoDAO().insertCalculoFondo(calculoFondo);
        this.view.getTableModel().addRow(calculoFondo);
    }

    private void editarCalculoFondo(int valor, String descripcion) {
        this.editingCalculoFondo.setValor(valor);
        this.editingCalculoFondo.setDescripcion(descripcion);
        this.editingCalculoFondo.setCaja(this.caja);
        DAOManager.getCalculoFondoDAO().updateCalculoFondo(editingCalculoFondo);
        this.view.getTableModel().setCalculoFondo(this.editingId, this.editingCalculoFondo);
    }

    private void updateButtonsEnabled() {
        if (this.view.getTable().getSelectedRow() >= 0) {
            this.view.getEliminarButton().setEnabled(true);
            this.view.getEditarButton().setEnabled(true);
        } else {
            this.view.getEliminarButton().setEnabled(false);
            this.view.getEditarButton().setEnabled(false);
        }
    }

    private void updateResumen() {
        int fondo = this.view.getFondoField().getValue();
        int suma = DAOManager.getCalculoFondoDAO().getTotalCalculoFondo(this.caja);
        this.view.getSumaField().setValue(suma);
        this.view.getDepositoField().setValue(suma - fondo);
    }

    private void cleanInput() {
        this.view.getValorField().setValue(0);
        this.view.getDescripcionField().setText("");

    }

    private void normalizeInput() {
        if (this.view.getDescripcionField().getText() == null) {
            this.view.getDescripcionField().setText("");
        }

        this.view.getDescripcionField().setText(this.view.getDescripcionField().getText().trim());
    }

    private void resetFocus() {
        this.view.getValorField().requestFocus();
    }

    private class GuardarAction extends AbstractAction {
        @Override
        public void actionPerformed(ActionEvent e) {
            CalcularFondoController.this.guardarActionListener();
        }
    }

    private class UpdateResumenAction extends AbstractAction {
        @Override
        public void actionPerformed(ActionEvent e) {
            CalcularFondoController.this.updateResumen();
        }
    }
}
