#include <stdlib.h>
#include <math.h>
#include "noidZ.h"

extern SDL_Surface *screen;

int sable = 2000;
struct {
       float x;
       float y;
       float mass;
       float speedX;
       float speedY;
} sand[2002];
float sand_gravity = 0.035;
float rebound_friction = 0.060;
struct {
       int qty;
       int numb[2001];
} quad_sand[22][22];

void scan_sand(int limit)
{
     int numb;
       for (numb = 1; numb <= limit ; numb = numb+1)
       {
           	int m = (int)(10*(sand[numb].x + 1));
           	int k = (int)(10*(sand[numb].y + 1));
           	if (m <= 0) { m=1;}
           	if (k <= 0) { k=1;}
           	if (m >= 21) { m=19;}
           	if (k >= 21) { k=19;}
           	quad_sand[m][k].qty = quad_sand[m][k].qty + 1;
           	if (quad_sand[m][k].qty >= 2000) {quad_sand[m][k].qty = 1999;}
           	int blerk = quad_sand[m][k].qty;
           	quad_sand[m][k].numb[blerk] = numb;
       } 
}

void qvol_sand(void)
{    int m,k,q,n;
     for (m = 1;m <= 21; m = m+1)
     {   for (k = 1;k<=21;k=k+1)
         {   if (quad_sand[m][k].qty <= 0)  
             {  for (q = 1; q <= (quad_sand[m][k].qty); q = q+1)
                {   n = quad_sand[m][k].numb[q];
                    int radsand = (int)(sand[n].mass * 10);
                    if (radsand == 0) { radsand = 1; }
                    int xquad,yquad;
                    for (xquad = m-radsand;xquad<=m+radsand;xquad=xquad+1)
                    {   for (yquad=k-radsand;yquad<=k+radsand;yquad=yquad+1)
                        {
                            
                        }
                    }
                }                
                quad_sand[m][k].qty = 0;
             }              
         }
     }
}

void init_quad(void)
{
         int m,k,q,n;
     for (m = 1;m <= 21; m = m+1)
     {   for (k = 1;k<=21;k=k+1)
         {   quad_sand[m][k].qty = 1;              
         }
     }
}

void draw_sand(int limit)
{
     int numb;
       for (numb = 1; numb < limit ; numb = numb+1)
       {
           	brescircle(screen,sand[numb].mass/4,sand[numb].x,sand[numb].y,blue);
       }  
}

void permute_sand(int limit)
{
               int numb;
       for (numb = 1; numb < limit ; numb = numb+1)
       {
           sand[numb].y = sand[numb].y + sand[numb].speedY;
           sand[numb].x = sand[numb].x + sand[numb].speedX;
           if (sand[numb].y <= -1)
           {
                            sand[numb].speedY = fabs(sand[numb].speedY * (rebound_friction/sand[numb].mass));
                            sand[numb].y = -0.999;
           }
           if (sand[numb].x <= -1)
           {
                            sand[numb].speedX = fabs(sand[numb].speedX * (rebound_friction/sand[numb].mass));
                            sand[numb].x = -0.999;
           }
           if (sand[numb].y >= 1)
           {
                            sand[numb].speedY = 1-fabs(sand[numb].speedY * (rebound_friction/sand[numb].mass));
                            sand[numb].y = 0.999;
           }
           if (sand[numb].x >= 1)
           {
                            sand[numb].speedX = 1-fabs(sand[numb].speedX * (rebound_friction/sand[numb].mass));
                            sand[numb].x = 0.999;
           }
       }
}

void volume_sand(int limit)
{
     int dumb;
     for (dumb = 1; dumb < limit ; dumb = dumb+1)
     {         int numb;
               for (numb = dumb + 1; numb < limit ; numb = numb+1)
               {
                  if (numb != dumb)
                 {
                  float diffX;
                  float diffY;
                     if (sand[numb].y > sand[dumb].y)
                     {
                           diffY = fabs(sand[numb].y - sand[dumb].y);
                     } else {
                           diffY = fabs(sand[dumb].y - sand[numb].y);
                     }
                     if (sand[numb].x > sand[dumb].x)
                     {
                           diffX = fabs(sand[numb].x - sand[dumb].x);
                     } else {
                           diffX = fabs(sand[dumb].x - sand[numb].x);
                     }
                     if ((diffX <= (sand[numb].mass/40))&&(diffY <= (sand[numb].mass/40)))
                     {
                                /*
                                float tempdumbnumb = sand[dumb].speedX;
                                sand[dumb].speedX = sand[numb].speedX;
                                sand[numb].speedX = tempdumbnumb;
                                tempdumbnumb = sand[dumb].speedY;
                                sand[dumb].speedY = sand[numb].speedY;
                                sand[numb].speedY = tempdumbnumb
                                */
                                float masseA = sand[dumb].mass * sand[dumb].mass;
                                float forceAx = sand[dumb].speedX * masseA;
                                float forceAy = sand[dumb].speedY * masseA;
                                float masseB = sand[numb].mass * sand[numb].mass;
                                float forceBx = sand[numb].speedX * masseB;
                                float forceBy = sand[numb].speedY * masseB;
                                forceAx = forceBx - forceAx;
                                forceAy = forceBy - forceAy;
                                forceBx = forceAx - forceBx;
                                forceBy = forceAy - forceBy;
                                sand[dumb].speedX = forceAx / masseA;
                                sand[dumb].speedY = forceAy / masseA;
                                sand[numb].speedX = forceBx / masseB;
                                sand[numb].speedY = forceBy / masseB;
                                sand[numb].x = sand[numb].x + sand[numb].speedX;
                                sand[numb].y = sand[numb].y + sand[numb].speedY;
                                sand[dumb].x = sand[dumb].x + sand[dumb].speedX;
                                sand[dumb].y = sand[dumb].y + sand[dumb].speedY;
                     }
                   }
                }
       }
}

void gravity_sand(int limit)
{
               int numb;
       for (numb = 1; numb < limit ; numb = numb+1)
       {
           sand[numb].speedY = sand[numb].speedY - (sand_gravity);
           }
}

void loop_sand(int max)
{
     	           draw_sand(max);
		           gravity_sand(max);
		           permute_sand(max);
		           //volume_sand(max);
		           scan_sand(max);
		           qvol_sand();
 }
 
 void init_sand(int limit)
{
     int numb;
       for (numb = 1; numb < limit ; numb = numb+1)
       {
           int chienne = rand();
           sand[numb].x = ((float)chienne / (RAND_MAX/2)-1);
           chienne = rand();
           sand[numb].y = ((float)chienne / (RAND_MAX));
           chienne = rand();
           sand[numb].mass = ((float)chienne / (RAND_MAX))/10;
           chienne = rand();
           sand[numb].speedX = (((float)chienne / (RAND_MAX/2))-1)/20;
           chienne = rand();
           sand[numb].speedY = (((float)chienne / (RAND_MAX)))/20;
       }    
       init_quad();
}
