package net.willware.Orbits;

import java.util.ArrayList;
import java.awt.Color;
import java.io.PrintStream;

/**
 * Created by IntelliJ IDEA.
 * User: wware
 * Date: Oct 16, 2004
 * Time: 9:52:10 AM
 */
public class System {

	public static boolean USE_GRAPHICS = true;
	static PrintStream out = java.lang.System.out;
	public static double time;
	public static final double INFINITY = 1.0e80;

	ArrayList things = new ArrayList();

	public void add(Object obj) {
		things.add(obj);
	}
	public int size() {
		return things.size();
	}
	public SimObject get(int index) {
		return (SimObject) things.get(index);
	}
	public void write() {
		for (int i = 0; i < things.size(); i++)
			get(i).write();
	}
	public void computeForces() throws Exception {
		for (int i = 0; i < things.size(); i++)
			for (int j = 0; j < things.size(); j++)
				if (i != j)
					get(i).interact(get(j));
	}
	public void integrate() throws Exception {
		for (int i = 0; i < things.size(); i++)
			get(i).timeStep1();
		for (int i = 0; i < things.size(); i++)
			get(i).timeStep2();
	}

	public System() {
		Earth = new PointMass(this, "Earth", earthMass,
				      new Vector(),
				      new Vector(0,
						 -earthMoonMassRatio * moonVelocity,
						 0),
				      DARKGREEN) {
				public void write() { }
				protected void init() {
					xmin = ymin = 1.0e20;
					xmax = ymax = -1.0e20;
					zeroForce();
					int N = 1000;
					for (int i = 0; i < N; i++) {
						double t = 2 * Math.PI * i / N;
						addPoint(earthRadius * Math.cos(t),
							 earthRadius * Math.sin(t));
					}
				}
			};
		Moon = new PointMass(this, "Moon",
				     earthMoonMassRatio * earthMass,
				     new Vector(moonDistance, 0, 0),
				     new Vector(0, moonVelocity, 0),
				     Color.GRAY);
		add(Earth);
		// add(Moon);
	}

	public void hack() throws Exception {
		time = 0.0;
		int modulo = 10;
		for (int i = 0; i < (tmax / dt); i++) {
			if ((i % modulo) == 0) write();
			computeForces();
			integrate();
			time += dt;
		}
		if (USE_GRAPHICS) {
			Grapher mygrapher = new Grapher(this);
			mygrapher.forceSquare();
		}
	}

	/* ------------------------------------ */

	/**
	 * Units are kg, m, sec
	 */
	public static final double mile = 1609.34;
	public static final double second = 1.0;
	public static final double minute = 60.0;
	public static final double hour = 60 * minute;
	public static final double day = 24 * hour;
	public static final double LunarMonth = 28 * day;

	public static double tmax = hour;
	public static double dt = 0.1;
	public static final double GravitationalConstant = 6.673e-11;
	public static PointMass Earth;
	public static PointMass Moon;

	public static final double earthMass = 5.9742e+24;
	public static final double earthRadius = 6.3781e+06;
	public static final double earthMoonMassRatio = 0.012;
	public static final double moonDistance = 3.6e8;
	public static final double moonVelocity =
	        Math.sqrt(GravitationalConstant * earthMass / moonDistance);
	public static final double earthRotationalVelocity =
	        (2 * Math.PI * earthRadius) / (24 * hour);
	public static final double earthGravity =
	        GravitationalConstant * earthMass /
	        (earthRadius * earthRadius);

	// Information on the Boeing 747-100
	// I'll assume this is typical for a spaceship
	// http://www.airliners.net/info/stats.main?id=97
	public static final double airplaneMass = 162386;
	public static final double airplaneVelocity = 907000 / hour;

	public static final double escapeVelocity = 11180.7;
	public static final double geoVelocity = 3072.01;
	public static final double geoRadius = 4.22431e+07;
	// LEO is about 200 km above the ground
	public static final double leoVelocity = 7784.85;
	public static final double leoRadius = 6.5781e+06;

	public static final double GM =
	        GravitationalConstant * earthMass;
	public static double circularVelocityFromRadius(double r) {
		return Math.sqrt(GM / r);
	}
	public static double circularRadiusFromVelocity(double v) {
		return GM / (v * v);
	}

	static Color DARKGREEN = new Color(0, 128, 0);
}
