import java.awt.*;
import java.awt.event.*;
import javax.swing.SwingUtilities;

import com.brackeen.javagamebook.graphics.*;
import com.brackeen.javagamebook.test.GameCore;

/**
    Prosty test rozglądania się za pomocą myszy. Użytkownik może 
    przesuwać kursor myszy w każdym kierunku niemal bez ograniczeń.
    Bez zastosowania tego efektu mysz zatrzymuje się na brzegu ekranu.
    <p>Mouselook korzysta z centrowania wskaźnika myszy po jej przesunięciu,
    dzięki czemu można obliczyć względne przesunięcie myszy
    i wskaźnik nigdy nie zatrzyma się na brzegu ekranu. */
public class MouselookTest extends GameCore
    implements MouseMotionListener, KeyListener
{

    public static void main(String[] args) {
        new MouselookTest().run();
    }

    private Image bgImage;
    private Robot robot;
    private Point mouseLocation;
    private Point centerLocation;
    private Point imageLocation;
    private boolean relativeMouseMode;
    private boolean isRecentering;

    public void init() {
        super.init();
        mouseLocation = new Point();
        centerLocation = new Point();
        imageLocation = new Point();

        relativeMouseMode = true;
        isRecentering = false;

        try {
            robot = new Robot();
            recenterMouse();
            mouseLocation.x = centerLocation.x;
            mouseLocation.y = centerLocation.y;
        }
        catch (AWTException ex) {
            System.out.println("Nie można utworzyć obiektu Robot!");
        }
        Window window = screen.getFullScreenWindow();
        window.addMouseMotionListener(this);
        window.addKeyListener(this);
        bgImage = loadImage("../images/background.jpg");
    }

    public synchronized void draw(Graphics2D g) {

        int w = screen.getWidth();
        int h = screen.getHeight();

        // Upewnij się, że położenie jest prawidłowe:
        imageLocation.x %= w;
        imageLocation.y %= screen.getHeight();
        if (imageLocation.x < 0) {
            imageLocation.x += w;
        }
        if (imageLocation.y < 0) {
            imageLocation.y += screen.getHeight();
        }

        // Narysowanie rysunku w czterech miejscach, 
        // co powoduje pokrycie nim całego ekranu.
        int x = imageLocation.x;
        int y = imageLocation.y;
        g.drawImage(bgImage, x, y, null);
        g.drawImage(bgImage, x-w, y, null);
        g.drawImage(bgImage, x, y-h, null);
        g.drawImage(bgImage, x-w, y-h, null);

        // Ustawienia rysowania:
        g.setRenderingHint(
                RenderingHints.KEY_TEXT_ANTIALIASING,
                RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
        g.drawString("Naciśnij spację, aby zmienić tryb myszy.", 5,
            FONT_SIZE);
        g.drawString("Naciśnij Escape, aby zakończyć.", 5, FONT_SIZE*2);
    }

    /**
        Zastosowanie klasy Robot do ustawienia 
        wskaźnika myszy na środku ekranu.
        <p>Należy pamiętać, że na niektórych platformach 
        funkcja ta jest niedostępna.
    */
    private synchronized void recenterMouse() {
        Window window = screen.getFullScreenWindow();
        if (robot != null && window.isShowing()) {
            centerLocation.x = window.getWidth() / 2;
            centerLocation.y = window.getHeight() / 2;
            SwingUtilities.convertPointToScreen(centerLocation,
                window);
            isRecentering = true;
            robot.mouseMove(centerLocation.x, centerLocation.y);
        }
    }

    // Z interfejsu MouseMotionListener:
    public void mouseDragged(MouseEvent e) {
        mouseMoved(e);
    }

    // Z interfejsu MouseMotionListener:
    public synchronized void mouseMoved(MouseEvent e) {
        // Jest to zdarzenie centrowania wskaźnika myszy – należy je zignorować.
        if (isRecentering &&
            centerLocation.x == e.getX() &&
            centerLocation.y == e.getY())
        {
            isRecentering = false;
        }
        else {
            int dx = e.getX() - mouseLocation.x;
            int dy = e.getY() - mouseLocation.y;
            imageLocation.x += dx;
            imageLocation.y += dy;
            // Centrowanie wskaźnika myszy:
            if (relativeMouseMode) {
                recenterMouse();
            }
        }
        mouseLocation.x = e.getX();
        mouseLocation.y = e.getY();
    }

    // Z interfejsu KeyListener:
    public void keyPressed(KeyEvent e) {
        if (e.getKeyCode() == KeyEvent.VK_ESCAPE) {
            // Zakończenie programu:
            stop();
        }
        else if (e.getKeyCode() == KeyEvent.VK_SPACE) {
            // Zmiana trybu względnego myszy:
            relativeMouseMode = !relativeMouseMode;
        }
    }

    // Z interfejsu KeyListener:
    public void keyReleased(KeyEvent e) {
        // Nic nie wykonuj.
    }

    // Z interfejsu KeyListener:
    public void keyTyped(KeyEvent e) {
        // Nic nie wykonuj.
    }
}
