package de.renew.layoutwindow;

import java.awt.KeyboardFocusManager;
import java.awt.Rectangle;
import java.awt.event.KeyEvent;
import java.util.Collections;
import java.util.Vector;
import javax.swing.JFormattedTextField;

import CH.ifa.draw.DrawPlugin;
import CH.ifa.draw.application.DrawApplication;
import de.renew.draw.storables.ontology.Drawing;
import de.renew.draw.storables.ontology.DrawingChangeEvent;
import de.renew.draw.storables.ontology.DrawingChangeListener;
import de.renew.draw.storables.ontology.DrawingListener;
import de.renew.draw.storables.ontology.Figure;

/**
 * This class tracks and updates the position and size of a selected figure
 * based on user input from formatted text fields for X, Y, width, and height.
 * It listens for changes in the drawing and updates the fields accordingly.
 */
public class PositionDimensionsTracker implements DrawingListener, DrawingChangeListener {

    private static final org.apache.log4j.Logger LOGGER =
        org.apache.log4j.Logger.getLogger(PositionDimensionsTracker.class);

    private final JFormattedTextField _xTextField;
    private final JFormattedTextField _yTextField;
    private final JFormattedTextField _widthTextField;
    private final JFormattedTextField _heightTextField;

    /**
     * Constructs a new tracker that synchronizes drawing figure position and dimensions
     * with the given formatted text fields.
     *
     * @param xTextField Field for the x coordinate
     * @param yTextField Field for the y coordinate
     * @param widthTextField Field for the width
     * @param heightTextField Field for the height
     */
    public PositionDimensionsTracker(
        JFormattedTextField xTextField, JFormattedTextField yTextField,
        JFormattedTextField widthTextField, JFormattedTextField heightTextField)
    {
        this._xTextField = xTextField;
        this._yTextField = yTextField;
        this._widthTextField = widthTextField;
        this._heightTextField = heightTextField;

        this._xTextField.addActionListener(e -> updateFigure());
        this._yTextField.addActionListener(e -> updateFigure());
        this._widthTextField.addActionListener(e -> updateFigure());
        this._heightTextField.addActionListener(e -> updateFigure());



        xTextField.setFocusTraversalKeys(
            KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, Collections.emptySet());
        yTextField.setFocusTraversalKeys(
            KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, Collections.emptySet());
        widthTextField.setFocusTraversalKeys(
            KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, Collections.emptySet());
        heightTextField.setFocusTraversalKeys(
            KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, Collections.emptySet());

        this._xTextField.addKeyListener(new java.awt.event.KeyAdapter() {
            @Override
            public void keyPressed(java.awt.event.KeyEvent evt) {
                if (evt.getKeyCode() == KeyEvent.VK_TAB) {
                    updateFigure();
                    yTextField.grabFocus();
                }
            }
        });

        this._yTextField.addKeyListener(new java.awt.event.KeyAdapter() {
            @Override
            public void keyPressed(java.awt.event.KeyEvent evt) {
                if (evt.getKeyCode() == KeyEvent.VK_TAB) {
                    updateFigure();
                    widthTextField.grabFocus();
                }
            }
        });

        this._widthTextField.addKeyListener(new java.awt.event.KeyAdapter() {
            @Override
            public void keyPressed(java.awt.event.KeyEvent evt) {
                if (evt.getKeyCode() == KeyEvent.VK_TAB) {
                    updateFigure();
                    heightTextField.grabFocus();
                }
            }
        });

        this._heightTextField.addKeyListener(new java.awt.event.KeyAdapter() {
            @Override
            public void keyPressed(java.awt.event.KeyEvent evt) {
                if (evt.getKeyCode() == KeyEvent.VK_TAB) {
                    updateFigure();
                    xTextField.grabFocus();
                }
            }
        });

        DrawApplication app = DrawPlugin.getGui();
        app.addDrawingListener(this);

        Collections.list(app.drawings()).forEach(d -> d.addDrawingChangeListener(this));
    }

    private void updateFigure() {
        Vector<Figure> selection = DrawPlugin.getGui().view().selection();
        if (selection.size() == 1) {
            try {
                int x = Integer.parseInt(_xTextField.getText());
                int y = Integer.parseInt(_yTextField.getText());
                int width = Integer.parseInt(_widthTextField.getText());
                int height = Integer.parseInt(_heightTextField.getText());
                Rectangle r = new Rectangle(x, y, width, height);
                Figure f = selection.firstElement();
                f.displayBox(r);
                f.invalidate();
                f.changed();
                DrawPlugin.getGui().view().checkDamage();
            } catch (NumberFormatException e) {
                LOGGER.warn(e.getMessage());
            }
        }
    }

    @Override
    public void drawingReleased(Drawing drawing) {
        drawing.removeDrawingChangeListener(this);
    }

    @Override
    public void drawingAdded(Drawing drawing) {
        drawing.addDrawingChangeListener(this);
    }

    @Override
    public void drawingInvalidated(DrawingChangeEvent e) {
        Vector<Figure> selection = DrawPlugin.getGui().view().selection();
        if (selection.size() == 1) {
            Figure f = selection.firstElement();
            Rectangle r = f.displayBox();
            _xTextField.setText("" + r.x);
            _yTextField.setText("" + r.y);
            _widthTextField.setText("" + r.width);
            _heightTextField.setText("" + r.height);
        } else {
            _xTextField.setText("");
            _yTextField.setText("");
            _widthTextField.setText("");
            _heightTextField.setText("");
        }
    }

    @Override
    public void drawingRequestUpdate(DrawingChangeEvent e) {}
}
