package com.savoirfairelinux.sflphone.model;

import java.util.ArrayList;
import java.util.List;

import android.graphics.PointF;

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

	private long lastUpdate = 0;
	public int width, height;
	private ArrayList<Bubble> bubbles = new ArrayList<Bubble>();
	private 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 addBubble(Bubble b) {
		b.setDensity(density);
		bubbles.add(b);
	}

	public List<Bubble> getBubbles()
	{
		return bubbles;
	}

	public void addAttractor(Attractor a) {
		a.setDensity(density);
		attractors.add(a);
	}

	public List<Attractor> getAttractors()
	{
		return attractors;
	}

	public void clearAttractors() {
		attractors.clear();
	}

	public void clear() {
		clearAttractors();
		bubbles.clear();
	}

	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=bubbles.size(); i<n; i++) {
			Bubble b = bubbles.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(int j=0; j<attr_n; j++) {
					Attractor t = attractors.get(j);
					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) {
					b.dragged = false;
					if(attractor.callback.onBubbleSucked(b)) {
						bubbles.remove(b);
						n--;
					} else {
						b.target_scale = 1.f;
					}
				}
			}

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

		}
	}


}
