package com.savoirfairelinux.sflphone.model;

import java.util.ArrayList;

import android.graphics.PointF;
import android.util.Log;

public class BubbleModel
{
	private static final String TAG = BubbleModel.class.getSimpleName();

	public long lastUpdate = 0;
	public int width, height;
	public ArrayList<Bubble> listBubbles = new ArrayList<Bubble>();
	public ArrayList<Attractor> attractors = new ArrayList<Attractor>();

	private static final float ATTRACTOR_DIST_SUCK = 20.f;

	private static final double BUBBLE_RETURN_TIME_HALF_LIFE = .25;
	private static final double BUBBLE_RETURN_TIME_LAMBDA = Math.log(2)/BUBBLE_RETURN_TIME_HALF_LIFE;

	/*private static final float FRICTION_VISCOUS = .5f;		// Viscous friction factor

	private static final float BUBBLE_MAX_SPEED = 2500.f;	// Max target speed in px/sec
	private static final float ATTRACTOR_SMOOTH_DIST = 100.f;// Size of the "gravity hole" around the attractor
	private static final float ATTRACTOR_STALL_DIST = 15.f; // Size of the "gravity hole" flat bottom
	private static final float ATTRACTOR_ACCEL = 10.f;		// Acceleration factor towards target speed
	 */
	public void update()
	{
		long now = System.nanoTime();

		// Do nothing if lastUpdate is in the future.
		if (lastUpdate > now)
			return;

		double ddt = Math.min((now - lastUpdate) / 1000000000.0, .2);
		lastUpdate = now;

		float dt = (float)ddt;
		//Log.w(TAG, "update dt="+dt);

		int attr_n = attractors.size();

		// Iterators should not be used in frequently called methods
		// to avoid garbage collection glitches caused by iterator objects.
		for(int i=0, n=listBubbles.size(); i<n; i++) {
			Bubble b = listBubbles.get(i);
			//Log.w(TAG, "update b");

			if(!b.dragged) {
				float bx=b.getPosX(), by=b.getPosY();

				Attractor attractor = null;
				PointF attractor_pos = b.attractor;
				float attractor_dist = (attractor_pos.x-bx)*(attractor_pos.x-bx) + (attractor_pos.y-by)*(attractor_pos.x-by);

				for(Attractor t : attractors) {
					float dx = t.pos.x-bx, dy = t.pos.y-by;
					float adist = dx*dx + dy*dy;
					if(adist < attractor_dist) {
						attractor = t;
						attractor_pos = t.pos;
						attractor_dist = adist;
					}
				}

				double edt = -Math.expm1(-BUBBLE_RETURN_TIME_LAMBDA*dt);
				double dx = (attractor_pos.x - bx) * edt;
				double dy = (attractor_pos.y - by) * edt;
//				Log.w(TAG, "update dx="+dt+" dy="+dy);
				b.setPos((float)(bx+dx), (float)(by+dy));

				if(attractor != null && attractor_dist < ATTRACTOR_DIST_SUCK*ATTRACTOR_DIST_SUCK) {
					attractor.callback.onBubbleSucked(b);
					listBubbles.remove(b);
					n--;
				}

				/*	float bx=b.getPosX(), by=b.getPosY();
				/// Apply viscous friction
				float friction_coef = 1.f-FRICTION_VISCOUS*dt;
				float tdx = b.attractor.x - bx, tdy = b.attractor.y - by;
				float dist = (float) Math.sqrt(tdx*tdx + tdy*tdy);
				float speed = (float)Math.sqrt(b.speed.x*b.speed.x + b.speed.y*b.speed.y);

				b.speed.x *= friction_coef;
				b.speed.y *= friction_coef;


				if(speed > 10.f || dist > ATTRACTOR_STALL_DIST) {
					dist = Math.max(1.f, dist); // Avoid division by 0

					b.speed.x *= friction_coef;
					b.speed.y *= friction_coef;

					// Target speed (defines the "gravity hole")
					float target_speed;
					if(dist > ATTRACTOR_SMOOTH_DIST)
						target_speed = BUBBLE_MAX_SPEED;
					else if(dist < ATTRACTOR_STALL_DIST)
						target_speed = 0;
					else
						target_speed = BUBBLE_MAX_SPEED/(ATTRACTOR_SMOOTH_DIST-ATTRACTOR_STALL_DIST)*(dist-ATTRACTOR_STALL_DIST);

					float target_speed_x = target_speed*tdx/dist;
					float target_speed_y = target_speed*tdy/dist;

					// Acceleration
					float ax = (target_speed_x-b.speed.x) * ATTRACTOR_ACCEL;// + 2*(b.last_speed.x-b.speed.x)*(1-FRICTION_VISCOUS)/FRICTION_VISCOUS*60.f;
					float ay = (target_speed_y-b.speed.y) * ATTRACTOR_ACCEL;// + 2*(b.last_speed.y-b.speed.y)*(1-FRICTION_VISCOUS)/FRICTION_VISCOUS*60.f;

					// Speed update

					b.speed.x += ax*dt;
					b.speed.y += ay*dt;
					b.last_speed.set(b.speed);
					Log.w(TAG, "dist " + dist + " speed " + Math.sqrt(b.speed.x*b.speed.x + b.speed.y*b.speed.y) + " target speed "+target_speed);

					// Position update
					float dx = b.speed.x * dt;
					float dy = b.speed.y * dt;
					b.setPos(bx+dx, by+dy);

				}
				// Prevent speed higher than BUBBLE_MAX_SPEED

				float ds = (target_speed-speed)*dt;

				// Set motion direction and speed
				float nsr = (speed>BUBBLE_MAX_SPEED ? BUBBLE_MAX_SPEED : speed+ds)/(dist < 1.f ? 1.f : dist);
				b.speed.x = tdx * nsr;
				b.speed.y = tdy * nsr;*/


			}

		}
	}
}
