package org.sflphone.model;

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

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

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) {
        Log.d(TAG, "Creating BubbleModel");
        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++) {

            if (i > bubbles.size()) { // prevent updating a bubble already removed
                return;
            }
            Bubble b = bubbles.get(i);

            if (b.markedToDie) {
                continue;
            }

            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.y - by);

                for (int j = 0; j < attr_n; j++) {
                    try {
                        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;
                        }
                    } catch (IndexOutOfBoundsException e) {
                        // Try to update when layout was changing
                    }
                }

                // 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);

        }
    }

    public Bubble getBubble(String call) {
        for (Bubble b : bubbles) {
            if (!b.isUser && b.callIDEquals(call))
                return b;
        }
        return null;
    }

    public void removeBubble(SipCall sipCall) {
        bubbles.remove(getBubble(sipCall.getCallId()));

    }

    public Bubble getUser() {
        for (Bubble b : bubbles) {
            if (b.isUser)
                return b;
        }
        return null;
    }

}
