/*
 * GPLv2 or 3, Copyright (c) 2010  Andrzej Zaborowski
 *
 * Implements a fake MapView that we can pass to WMSLayer's .paint,
 * this will give us two things:
 *  # We'll be able to tell WMSLayer.paint() what area we want it
 *    to download (it ignores the "bounds" parameter) and override
 *    isVisible and friends as needed, and
 *  # We'll receive notifications from Grabber when we need to
 *    repaint (and call WMSLayer's .paint again) because the
 *    Grabber downloaded some or all of the tiles that we asked
 *    WMSLayer for and WMSLayer created the Grabber passing it
 *    our MapView.  Otherwise we wouldn't be able to tell when
 *    this happened and could only guess.
 */
package wmsturbochallenge;

import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.image.BufferedImage;

import org.openstreetmap.josm.data.ProjectionBounds;
import org.openstreetmap.josm.data.coor.EastNorth;
import org.openstreetmap.josm.gui.MapView;

class fake_map_view extends MapView {
	public ProjectionBounds view_bounds;
	public MapView parent;

	public Graphics2D graphics;
	public BufferedImage ground_image;
	public int ground_width = -1;
	public int ground_height = -1;
	public double scale;
	public double max_east_west;

	public fake_map_view(MapView parent, double scale) {
		super(null); //TODO MapView constructor contains registering listeners and other code, that probably shouldn't be called in fake map view
		this.parent = parent;
		this.scale = scale;

		ProjectionBounds parent_bounds = parent.getProjectionBounds();
		max_east_west =
			parent_bounds.max.east() - parent_bounds.min.east();
	}

	public void setProjectionBounds(ProjectionBounds bounds) {
		view_bounds = bounds;

		if (bounds.max.east() - bounds.min.east() > max_east_west) {
			max_east_west = bounds.max.east() - bounds.min.east();

			/* We need to set the parent MapView's bounds (i.e.
			 * zoom level) to the same as ours max possible
			 * bounds to avoid WMSLayer thinking we're zoomed
			 * out more than we are or it'll pop up an annoying
			 * "requested area is too large" popup.
			 */
			EastNorth parent_center = parent.getCenter();
			parent.zoomTo(new ProjectionBounds(
					new EastNorth(
						parent_center.east() -
						max_east_west / 2,
						parent_center.north()),
					new EastNorth(
						parent_center.east() +
						max_east_west / 2,
						parent_center.north())));

			/* Request again because NavigatableContent adds
			 * a border just to be sure.
			 */
			ProjectionBounds new_bounds =
				parent.getProjectionBounds();
			max_east_west =
				new_bounds.max.east() - new_bounds.min.east();
		}

		Point vmin = getPoint(bounds.min);
		Point vmax = getPoint(bounds.max);
		int w = vmax.x + 1;
		int h = vmin.y + 1;

		if (w <= ground_width && h <= ground_height) {
			graphics.setClip(0, 0, w, h);
			return;
		}

		if (w > ground_width)
			ground_width = w;
		if (h > ground_height)
			ground_height = h;

		ground_image = new BufferedImage(ground_width,
				ground_height,
				BufferedImage.TYPE_INT_RGB);
		graphics = ground_image.createGraphics();
		graphics.setClip(0, 0, w, h);
	}

	public ProjectionBounds getProjectionBounds() {
		return view_bounds;
	}

	public Point getPoint(EastNorth p) {
		double x = p.east() - view_bounds.min.east();
		double y = view_bounds.max.north() - p.north();
		x /= this.scale;
		y /= this.scale;

		return new Point((int) x, (int) y);
	}

	public EastNorth getEastNorth(int x, int y) {
		return new EastNorth(
			view_bounds.min.east() + x * this.scale,
			view_bounds.min.north() - y * this.scale);
	}

	public boolean isVisible(int x, int y) {
		return true;
	}

	public Graphics getGraphics() {
		return graphics;
	}

	public void repaint() {
	}
}
