package net.willware.Orbits;

import java.awt.Canvas;
import java.awt.GridLayout;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.MouseListener;
import java.awt.event.MouseEvent;
import java.text.DecimalFormat;

import javax.swing.JFrame;
import javax.swing.JPanel;

public class Grapher extends JFrame implements MouseListener {

	double xMin, xMax, yMin, yMax;
	double xMinOrig, xMaxOrig, yMinOrig, yMaxOrig;
	int frmWidth = 500;
	int frmHeight = 500;
	int width;
	int height;
	MyCanvas canvas;
	System system;

	public void mouseEntered(MouseEvent e) { }
	public void mouseExited(MouseEvent e) { }
	public void mousePressed(MouseEvent e) { }
	public void mouseReleased(MouseEvent e) { }

	public void mouseClicked(MouseEvent e) {
		double FACTOR = 2.0;
		double x = canvas.getPhysicalX(e.getX());
		double y = canvas.getPhysicalY(e.getY());
		String[] fields = e.paramString().split(",");
		int button = new Integer(fields[3].split("=")[1]).intValue();
		switch (button) {
			case 1:
				// left button, zoom in
				scaleCanvas(x, y, 1/FACTOR);
				break;
			case 2:
				// middle button, recenter without zooming
				scaleCanvas(x, y, 1);
				break;
			case 3:
				// right button, zoom out
				scaleCanvas(x, y, FACTOR);
				break;
		}
	}
	private void scaleCanvas(double x, double y, double factor) {
		double xspread = (xMax - xMin) / 2;
		double yspread = (yMax - yMin) / 2;
		xspread *= factor;
		yspread *= factor;
		xMin = x - xspread;
		xMax = x + xspread;
		yMin = y - yspread;
		yMax = y + yspread;
		canvas.repaint();

	}

	public void forceSquare() {
		double xcenter = (xMax + xMin) / 2;
		double ycenter = (yMax + yMin) / 2;
		double xdelta = (xMax - xMin) / 2;
		double ydelta = (yMax - yMin) / 2;
		if (xdelta > ydelta)
			ydelta = xdelta;
		else
			xdelta = ydelta;
		xMin = xcenter - xdelta;
		xMax = xcenter + xdelta;
		yMin = ycenter - ydelta;
		yMax = ycenter + ydelta;
		xMinOrig = xMin; xMaxOrig = xMax;
		yMinOrig = yMin; yMaxOrig = yMax;
		repaint();
	}
	public void expandLimits(double xmin, double xmax,
	                         double ymin, double ymax) {
		if (xmin < xMin) xMin = xmin;
		if (xmax > xMax) xMax = xmax;
		if (ymin < yMin) yMin = ymin;
		if (ymax > yMax) yMax = ymax;
	}

	public Grapher(System c) {
		system = c;
		xMin = yMin = 1.0e20;
		xMax = yMax = -1.0e20;
		for (int i = 0; i < c.size(); i++)
			c.get(i).growBoundingBox(this);
		JPanel canvasPanel = new JPanel();
		canvasPanel.setLayout(
		        new GridLayout(0, 1));
		canvas = new MyCanvas();
		canvas.owner = this;
		canvas.addMouseListener(this);
		canvas.setBackground(Color.WHITE);
		canvasPanel.add(canvas);
		getContentPane().add(canvasPanel);
		setBounds(0, 0, frmWidth, frmHeight);
		setTitle("Launch system simulator");
		java.lang.System.out.println("Grapher class derived from Graph01, " +
		        "(c) 2002, Richard G. Baldwin");
		java.lang.System.out.println("http://www.developer.com/" +
		        "java/other/article.php/10936_1554511_2");
		setVisible(true);
		setDefaultCloseOperation(EXIT_ON_CLOSE);
		width = canvas.getWidth();
		height = canvas.getHeight();
		scaleCanvas((xMin + xMax) / 2,
		        (yMin + yMax) / 2,
		        1.05);
	}
	class MyCanvas extends Canvas {
		double xScale;
		double yScale;
		DecimalFormat df = new DecimalFormat("0.00");
		Grapher owner;
		public void paint(Graphics g) {
			xScale = width / (xMax - xMin);
			yScale = height / (yMax - yMin);
			for (int i = 0; i < system.size(); i++) {
				SimObject obj = system.get(i);
				obj.draw(g, owner);
			}
			double width = xMax - xMin;
			double wmiles = width * 6.2137e-4;
			String wstr;
			if (width < 1000) {
				wstr = df.format(width) + " m    ";
			} else if (width < 1.0e6) {
				wstr = df.format(width / 1000) + " km    ";
			} else {
				wstr = df.format(width / 1.0e6) + " Mm    ";
			}
			if (wmiles < 1) {
				wstr += df.format(wmiles * 5280) + " ft";
			} else if (wmiles < 1000) {
				wstr += df.format(wmiles) + " miles";
			} else {
				wstr += df.format(wmiles / 1000) + " Kmiles";
			}
			g.setColor(Color.BLACK);
			g.drawString(wstr, 20, 20);
		}
		int getScreenX(double x) {
			return (int) ((x - xMin) * xScale);
		}
		int getScreenY(double y) {
			double yDoub = yMax - y;
			int yInt = (int) (yDoub * yScale);
			return yInt;
		}
		double getPhysicalX(int x) {
			return (x / xScale) + xMin;
		}
		double getPhysicalY(int y) {
			return yMax - (y / yScale);
		}
	}
}
