package com.savoirfairelinux.sflphone.model;

import java.util.ArrayList;

import android.graphics.PointF;

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 double BUBBLE_RETURN_TIME_HALF_LIFE = .3;
	private static final double BUBBLE_RETURN_TIME_LAMBDA = Math.log(2)/BUBBLE_RETURN_TIME_HALF_LIFE;

	private static final double FRICTION_VISCOUS = Math.log(2)/.2f;		// Viscous friction factor

	private static final float BUBBLE_MAX_SPEED = 2500.f;	// px.s-1 : Max target speed in px/sec
	private static final float ATTRACTOR_SMOOTH_DIST = 50.f; // px : Size of the "gravity hole" around the attractor
	private static final float ATTRACTOR_STALL_DIST = 15.f; // px : Size of the "gravity hole" flat bottom
	private static final float ATTRACTOR_DIST_SUCK = 20.f; // px

	private static final float BORDER_REPULSION = 60000; // px.s^-2

	private final float border_repulsion;
	private final float bubble_max_speed;
	private final float attractor_smooth_dist;
	private final float attractor_stall_dist;
	private final float attractor_dist_suck;

	private float density = 1.f;

	public BubbleModel(float screen_density) {
		this.density = screen_density;
		attractor_dist_suck = ATTRACTOR_DIST_SUCK*density;
		bubble_max_speed = BUBBLE_MAX_SPEED*density;
		attractor_smooth_dist = ATTRACTOR_SMOOTH_DIST*density;
		attractor_stall_dist = ATTRACTOR_STALL_DIST*density;
		border_repulsion = BORDER_REPULSION*density;
	}

	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;
					}
				}

				//float friction_coef = 1.f-FRICTION_VISCOUS*dt;
				double friction_coef = 1+Math.expm1(-FRICTION_VISCOUS*ddt);
				b.speed.x *= friction_coef;
				b.speed.y *= friction_coef;

				//if(attractor != null) {
				float target_speed;
				float tdx = attractor_pos.x - bx, tdy = attractor_pos.y - by;
				float dist = Math.max(1.f, (float) Math.sqrt(tdx*tdx + tdy*tdy));
				if(dist > attractor_smooth_dist)
					target_speed = bubble_max_speed;
				else if(dist < attractor_stall_dist)
					target_speed = 0;
				else {
					float a = (dist-attractor_stall_dist)/(attractor_smooth_dist-attractor_stall_dist);
					target_speed = bubble_max_speed*a;
				}
				if(attractor != null) {
					if(dist > attractor_smooth_dist)
						b.target_scale = 1.f;
					else if(dist < attractor_stall_dist)
						b.target_scale = .2f;
					else {
						float a = (dist-attractor_stall_dist)/(attractor_smooth_dist-attractor_stall_dist);
						b.target_scale = a*.8f+.2f;
					}

				}

				// border repulsion
				if(bx < 0 && b.speed.x < 0) {
					b.speed.x += dt * border_repulsion;
				} else if(bx > width && b.speed.x > 0) {
					b.speed.x -= dt * border_repulsion;
				}
				if(by < 0 && b.speed.y < 0) {
					b.speed.y += dt * border_repulsion;
				} else if(by > height && b.speed.y > 0) {
					b.speed.y -= dt * border_repulsion;
				}


				b.speed.x += dt * target_speed * tdx/dist;
				b.speed.y += dt * target_speed * tdy/dist;

				double edt = -Math.expm1(-BUBBLE_RETURN_TIME_LAMBDA*ddt);
				double dx = (attractor_pos.x - bx) * edt + Math.min(bubble_max_speed, b.speed.x) * dt;
				double dy = (attractor_pos.y - by) * edt + Math.min(bubble_max_speed, b.speed.y) * dt;
				//	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--;
				}
			}

			b.setScale(b.getScale() + (b.target_scale-b.getScale())*dt*10.f);

		}
	}
}
