/*
 * Copyright 2014 MovingBlocks
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.terasology.worldviewer.camera;

import java.awt.Component;
import java.awt.Point;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseWheelEvent;

import javax.swing.SwingUtilities;

import org.terasology.math.TeraMath;

/**
 * Controls a camera based on mouse interaction
 * @author Martin Steiger
 */
public class CameraMouseController extends MouseAdapter {

    private Point draggedPoint;
    private final Camera camera;

    private int zoomLevel;
    private int minZoomLevel = -8;
    private int maxzoomLevel = 12;

    public CameraMouseController(Camera camera) {
        this.camera = camera;
    }

    @Override
    public void mouseDragged(MouseEvent e) {
        if (draggedPoint != null) {
            int dx = draggedPoint.x - e.getX();
            int dy = draggedPoint.y - e.getY();
            draggedPoint.setLocation(e.getPoint());
            camera.translate(dx, dy);
        }
    }

    @Override
    public void mousePressed(MouseEvent e) {
        if (SwingUtilities.isRightMouseButton(e)) {
            draggedPoint = e.getPoint();
        }
    }

    @Override
    public void mouseReleased(MouseEvent e) {
        draggedPoint = null;
    }

    @Override
    public void mouseWheelMoved(MouseWheelEvent e) {
        zoomLevel += e.getWheelRotation();

        zoomLevel = TeraMath.clamp(zoomLevel, minZoomLevel, maxzoomLevel);

        float delta = 0.25f;

        // Zoom only in deterministic steps
        // Don't concatenate with previous zooms to avoid rounding errors
        float zoom = (float) Math.pow(2.0, zoomLevel * delta);

        // This cast is safe since MouseWheelEvent takes only Component sources
        Component source = (Component) e.getSource();

        int relX = e.getX() - source.getWidth() / 2;
        int relY = e.getY() - source.getHeight() / 2;

        int oldX = TeraMath.floorToInt(relX);
        int oldY = TeraMath.floorToInt(relY);

        // move the camera to the cursor position
        camera.translate(oldX, oldY);

        // zoom
        camera.setZoom(zoom);

        int newX = TeraMath.floorToInt(relX);
        int newY = TeraMath.floorToInt(relY);

        // revert the camera movement from above, but in the new coordinate system
        camera.translate(-newX, -newY);
    }
}

@@ -1149,25 +1149,25 @@
 vate int max
-z
+Z
 oomLevel = 1
@@ -1166,17 +1166,17 @@
 evel = 1
-2
+6
 ;%0A%0A    p
@@ -1994,17 +1994,17 @@
 vel, max
-z
+Z
 oomLevel

Increase max. zoom level to 16x