package me.teridax.jcash.gui.login;

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

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

import static me.teridax.jcash.gui.Utils.addGridBagRow;
import static me.teridax.jcash.gui.Utils.addHeading;
import static me.teridax.jcash.lang.Translator.translate;

public class LoginView extends JPanel {

    /**
     * Maximum number of decimal digits that can be stored lossless by a 32-bit signed integer.
     * N = log10(2^32-1) = 9,632959861146281
     */
    private static final int MAX_PIN_DECIMAL_DIGITS = 9;

    private JFormattedTextField blz;
    private JFormattedTextField iban;
    private JPasswordField pin;
    private JButton login;

    public LoginView() {
        createComponents();
        layoutComponents();
    }

    private void layoutComponents() {
        var content = new JLabel();
        content.setIcon(new ImageIcon(IconProvider.getBackground()));
        content.setLayout(new BorderLayout());

        var loginPane = new JPanel(new GridBagLayout());
        loginPane.setOpaque(true);
        content.add(loginPane, BorderLayout.CENTER);
        content.add(Box.createHorizontalStrut(400), BorderLayout.WEST);

        this.setLayout(new BorderLayout(32, 32));
        this.add(new JScrollPane(content), BorderLayout.CENTER);

        var constraints = new GridBagConstraints();

        constraints.gridwidth = 4;
        constraints.insets = new Insets(12, 12, 12, 12);

        addGridBagRow(constraints, loginPane, new JLabel(addHeading(translate("Cashmachine"))), 0, "");
        addGridBagRow(constraints, loginPane, blz, 1, translate("BLZ"));
        addGridBagRow(constraints, loginPane, iban, 2, translate("IBAN"));
        addGridBagRow(constraints, loginPane, pin, 3, translate("PIN"));

        constraints.gridy = 4;
        constraints.anchor = GridBagConstraints.PAGE_END;
        constraints.weightx = 0;
        constraints.fill = GridBagConstraints.NONE;
        constraints.insets = new Insets(0, 0, 0, 12);
        loginPane.add(login, constraints);
    }

    private void createComponents() {
        this.blz = new JFormattedTextField();
        this.iban = new JFormattedTextField();
        this.pin = new JPasswordField();
        this.login = new JButton(translate("Login"));

        this.login.setFont(new Font("Circus", Font.PLAIN, 28));
        this.login.setBackground(Color.CYAN);

        restrictPasswordToDigits();
        restrictIbanInput();
    }

    /**
     * Adds a document filter onto {@link #pin} that filters out everything that is not a digit.
     * The filter also restricts the amount of digits that can be entered to {@link #MAX_PIN_DECIMAL_DIGITS}
     */
    private void restrictPasswordToDigits() {
        ((AbstractDocument) this.pin.getDocument()).setDocumentFilter(new DocumentFilter() {
            @Override
            public void replace(FilterBypass fb, int offset, int length, String text, AttributeSet attrs)
                    throws BadLocationException {
                String newText = fb.getDocument().getText(0, fb.getDocument().getLength()) + text;

                if (newText.matches(String.format("\\d{1,%s}", MAX_PIN_DECIMAL_DIGITS))) {
                    super.replace(fb, offset, length, text, attrs);
                }
            }
        });
    }

    /**
     * Adds a document filter onto {@link #iban} that filters out everything that is not a digit.
     * The filter also restricts the amount of digits that can be entered to {@link #MAX_PIN_DECIMAL_DIGITS}
     */
    private void restrictIbanInput() {
        ((AbstractDocument) this.iban.getDocument()).setDocumentFilter(new DocumentFilter() {
            @Override
            public void replace(FilterBypass fb, int offset, int length, String text, AttributeSet attrs)
                    throws BadLocationException {
                String newText = fb.getDocument().getText(0, fb.getDocument().getLength()) + text;

                if (newText.matches(String.format("\\d{1,%s}", MAX_PIN_DECIMAL_DIGITS))) {
                    super.replace(fb, offset, length, text, attrs);
                }
            }
        });
    }

    public JTextField getBlz() {
        return blz;
    }

    public JTextField getIban() {
        return iban;
    }

    public JPasswordField getPin() {
        return pin;
    }

    public JButton getLogin() {
        return login;
    }
}
