package me.teridax.jcash.gui.deposit;

import me.teridax.jcash.Logging;
import me.teridax.jcash.decode.StringDecoder;
import me.teridax.jcash.gui.IconProvider;
import me.teridax.jcash.gui.InvalidInputException;

import javax.swing.*;
import java.awt.*;
import java.text.ParseException;

import static me.teridax.jcash.lang.Translator.translate;

/**
 * View class for displaying a dialog prompting the user to
 * enter a valid amount to deposit at their account
 */
public class DepositView {

    /**
     * Window to use
     */
    private JDialog dialog;
    private JButton cancel;
    /**
     * Button for applying the deposit operation
     */
    private JButton deposit;
    /**
     * Displays the validated value to deposit
     */
    private JLabel enteredValue;
    /**
     * Displays the account balance after the deposit operation
     */
    private JLabel balanceAfterDeposit;
    private JFormattedTextField value;

    public DepositView(double maxValue) {
        createComponents(maxValue);
        layoutComponents();
    }

    public void showDialog() {
        dialog.setIconImage(IconProvider.getWindowIcon());
        dialog.setModalityType(Dialog.ModalityType.APPLICATION_MODAL);
        dialog.setTitle(translate("Deposit money"));
        dialog.pack();
        dialog.setSize(dialog.getWidth() * 2, dialog.getHeight());
        dialog.setResizable(false);
        dialog.setLocationRelativeTo(null);
        dialog.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        dialog.setVisible(true);
    }

    private void layoutComponents() {
        dialog.getContentPane().setLayout(new GridBagLayout());

        var c = new GridBagConstraints();

        c.gridx = 0;
        c.gridy = 0;
        c.gridwidth = 1;
        c.fill = GridBagConstraints.NONE;
        c.anchor = GridBagConstraints.LAST_LINE_END;
        c.weightx = 0;
        c.insets = new Insets(6, 6, 6, 6);
        dialog.getContentPane().add(new JLabel(translate("Value"), SwingConstants.RIGHT), c);

        c.gridx = 1;
        c.gridy = 0;
        c.fill = GridBagConstraints.HORIZONTAL;
        c.anchor = GridBagConstraints.LAST_LINE_END;
        c.weightx = 0.5;
        dialog.getContentPane().add(value, c);

        c.gridx = 2;
        c.gridy = 0;
        c.fill = GridBagConstraints.NONE;
        c.anchor = GridBagConstraints.LINE_START;
        c.weightx = 0;
        dialog.getContentPane().add(new JLabel("€"), c);

        c.gridx = 0;
        c.gridy = 1;
        c.gridwidth = 1;
        c.fill = GridBagConstraints.HORIZONTAL;
        c.anchor = GridBagConstraints.LAST_LINE_END;
        dialog.getContentPane().add(new JLabel(translate("Value to deposit:"), SwingConstants.RIGHT), c);

        c.gridx = 1;
        c.gridy = 1;
        c.gridwidth = 2;
        c.fill = GridBagConstraints.HORIZONTAL;
        c.anchor = GridBagConstraints.LAST_LINE_END;
        dialog.getContentPane().add(enteredValue, c);

        c.gridx = 0;
        c.gridy = 2;
        c.gridwidth = 1;
        c.fill = GridBagConstraints.HORIZONTAL;
        c.anchor = GridBagConstraints.LAST_LINE_END;
        dialog.getContentPane().add(new JLabel(translate("Balance after deposit:"), SwingConstants.RIGHT), c);

        c.gridx = 1;
        c.gridy = 2;
        c.gridwidth = 2;
        c.fill = GridBagConstraints.HORIZONTAL;
        c.anchor = GridBagConstraints.LAST_LINE_END;
        dialog.getContentPane().add(balanceAfterDeposit, c);

        var buttonPanel = new JPanel(new FlowLayout(FlowLayout.TRAILING));
        buttonPanel.add(cancel);
        buttonPanel.add(deposit);

        c.gridx = 0;
        c.gridy = 3;
        c.gridwidth = 3;
        c.fill = GridBagConstraints.HORIZONTAL;
        c.anchor = GridBagConstraints.LAST_LINE_END;
        dialog.getContentPane().add(buttonPanel, c);
    }

    private void createComponents(double maxValue) {
        this.dialog = new JDialog();

        this.cancel = new JButton(translate("Cancel"));
        this.deposit = new JButton(translate("Deposit"));
        this.value = new JFormattedTextField(StringDecoder.getNumberFormatter(Double.MAX_VALUE));
        this.enteredValue = new JLabel();
        this.balanceAfterDeposit = new JLabel(StringDecoder.getNumberFormat().format(maxValue));

        this.deposit.setEnabled(false);

        this.dialog.setContentPane(new JPanel(new GridBagLayout()));
    }

    /**
     * Returns the amount of money that should be deposited
     * This value derives from the input of the user.
     * @return the value to deposit
     * @throws InvalidInputException if the user entered something invalid
     */
    public double getAmount() throws InvalidInputException {
        if (value.getText().isBlank())
            throw new InvalidInputException("currency value is blank or has been invalid whilst entered");

        try {
            return StringDecoder.getNumberFormat().parse(value.getText()).doubleValue();
        } catch (ParseException e) {
            Logging.LOGGER.severe("Amount text field contains invalid value: " + value);
            throw new InvalidInputException(e);
        }
    }

    public JFormattedTextField getValue() {
        return value;
    }

    public JButton getCancel() {
        return cancel;
    }

    public JButton getDeposit() {
        return deposit;
    }

    public void dispose() {
        this.dialog.dispose();
    }

    /**
     * Sets the supplied amount to the preview GUI fields.
     * @param amount the value to display for value to deposit
     * @param after the value to display for balance after deposit
     */
    public void setCommittedValue(double amount, double after) {
        enteredValue.setText(StringDecoder.getNumberFormat().format(amount));
        balanceAfterDeposit.setText(StringDecoder.getNumberFormat().format(after));
    }
}
