//
//  Particle.m
//  gravity
//
//  Created by Mike Mintz on 12/31/05.
//  Copyright 2005 __MyCompanyName__. All rights reserved.
//

#import "Particle.h"

@implementation Particle

- (id)initWithDefaults: (ScreenSaverDefaults*)_defaults withViewSize: (NSSize)size withPosition: (NSPoint)p0 withVelocity: (NSPoint)v0 withMass: (float)m0 withCharge: (float)q0 {
	[self init];
	defaults = _defaults;
	[self loadDefaults];
	viewSize = size;
	position.x = p0.x;
	position.y = p0.y;
	velocity.x = v0.x;
	velocity.y = v0.y;
	restMass = m0;
	mass = restMass;
	mass = m0;
	charge = q0;
	return self;
}

- (void)loadDefaults {
	edgesOption = [defaults stringForKey: @"edges"];
	relativisticOption = [defaults stringForKey: @"relativistic"];
	gravityCoefficient = [defaults floatForKey: @"gravityCoefficient"];
	electricCoefficient = [defaults floatForKey: @"electricCoefficient"];
	maxSpeed = [defaults floatForKey: @"maxSpeed"];
}

- (NSPoint)position {
	return position;
}

- (NSPoint)velocity {
	return velocity;
}

- (float)mass {
	return mass;
}

- (float)restMass {
	return restMass;
}

- (float)charge {
	return charge;
}

- (void)moveOneFrame {
	if ([relativisticOption isEqualToString: @"Standard"]) {
		float vSquared;
		vSquared = (velocity.x) * (velocity.x) + (velocity.y) * (velocity.y);
		while (vSquared >= maxSpeed * maxSpeed) {
			velocity.x *= 0.99;
			velocity.y *= 0.99;
			vSquared = (velocity.x) * (velocity.x) + (velocity.y) * (velocity.y);
		}
		mass = restMass / sqrt(1 - vSquared / (maxSpeed * maxSpeed));
	} else if ([relativisticOption isEqualToString: @"Weird"]) {
		float vSquared;
		vSquared = (velocity.x) * (velocity.x) + (velocity.y) * (velocity.y);
		while (vSquared >= maxSpeed * maxSpeed) {
			velocity.x *= 0.9;
			velocity.y *= 0.9;
			vSquared = (velocity.x) * (velocity.x) + (velocity.y) * (velocity.y);
		}
	}
	if (mass <= 0) {
		mass = 0.1;
	}
    float a_x = netForce.x / mass;
    float a_y = netForce.y / mass;
	position.x += velocity.x + 0.5 * a_x;
	position.y += velocity.y + 0.5 * a_x;
	velocity.x += a_x;
    velocity.y += a_y;
	netForce.x = 0;
	netForce.y = 0;
}

- (void)stayOnScreenWithRadius: (float)radius {
	if ([edgesOption isEqualToString: @"Wrap"]) {
		if (position.x < -radius)
			position.x = viewSize.width + radius;
		else if (position.x > viewSize.width + radius)
			position.x = -radius;
		if (position.y < -radius)
			position.y = viewSize.height + radius;
		else if (position.y > viewSize.height + radius)
			position.y = -radius;
	} else if ([edgesOption isEqualToString: @"Bounce"]) {
		if (position.x < radius)
			velocity.x = fabs(velocity.x);
		else if (position.x > viewSize.width - radius)
			velocity.x = -fabs(velocity.x);
		if (position.y < radius)
			velocity.y = fabs(velocity.y);
		else if (position.y > viewSize.height - radius)
			velocity.y = -fabs(velocity.y);
	}
}

- (void)getInfluencedBy: (Particle*)other {
	NSPoint r;
	r.x = [other position].x - position.x;
	r.y = [other position].y - position.y;
	if ([edgesOption isEqualToString: @"Wrap"]) {
		if (fabs(r.x) > viewSize.width / 2.0) r.x = viewSize.width - r.x;
		if (fabs(r.y) > viewSize.height / 2.0) r.y = viewSize.height - r.y;
	}
	float rSquared = (r.x * r.x) + (r.y * r.y);
	float rMagnitude = sqrt(rSquared);
	if (rSquared <= 0) {
		rSquared = 0.00001;
	}
	if (rMagnitude <= 0) {
		rMagnitude = 0.00001;
	}
	float forceGravityMagnitude = gravityCoefficient * mass * [other mass] / rSquared;
	float forceElectricMagnitude = -1 * electricCoefficient * charge * [other charge] / rSquared;
	/*
	NSPoint forceGravity;
	forceGravity.x = r.x * forceGravityMagnitude / rMagnitude;
	forceGravity.y = r.y * forceGravityMagnitude / rMagnitude;
	NSPoint forceElectric;
	forceElectric.x = -r.x * forceElectricMagnitude / rMagnitude;
	forceElectric.y = -r.y * forceElectricMagnitude / rMagnitude;
	netForce.x += forceGravity.x + forceElectric.x;
	netForce.y += forceGravity.y + forceElectric.y;
	*/
	netForce.x += (forceGravityMagnitude + forceElectricMagnitude) * r.x / rMagnitude;
	netForce.y += (forceGravityMagnitude + forceElectricMagnitude) * r.y / rMagnitude;
}

@end
