#include <math.h>
#include <stdio.h>
#include <stdlib.h>

#include "atoms.h"
#include "physics.h"

atom atoms[MAXATOMS];
bond bonds[MAXBONDS];
atomgroup agroups[MAXGROUPS];

int atom_num = 0, bond_num = 0, agroup_num = 0;

extern atompoint atompoints[MAXATOMPOINTS];
extern triangle2d triangles[MAXTRIANGLES];
extern int atompoint_num, triangle_num;

extern float blobmassgravity;

extern int atomblockx;
extern int atomblocky;

void SetAtomColor(atom *a, unsigned char r, unsigned char g, unsigned char b)
{
    a->col.r = r;
    a->col.g = g;
    a->col.b = b;
}

void SetAtom(atom *a, int group, int size, float mass, float px, float py, float vx, float vy)
{
    a->grp = group;
    a->pos.x = px;
    a->pos.y = py;
    a->vel.x = vx;
    a->vel.y = vy;
    a->acl.x = XGRAVITY;
	a->acl.y = blobmassgravity;

    a->size = size;
    a->mass = mass;
    a->radius = pow(2,size+5)/2;
    a->nbonds = 0;
	a->exists = true;
}

void SetBond(bond *b, int a1, int a2, float bal, bool brk)
{
    b->atom1 = a1;
    b->atom2 = a2;
    b->balance = bal;
    b->broken = brk;
}

void CreateAtomBlock(int size, float mass, int xp, int yp, int ax, int ay, float xs, float ys)
{
    atomgroup *ag = &agroups[agroup_num];
    ag->atom_space = pow(2,size+3);

    int atomspace = ag->atom_space;
    ag->break_space = atomspace * 2;
    ag->deform_space = atomspace + 2;

    bool brk = false;
    
    int b1 = bond_num;

    int na = ax * ay;
    int nb = 5*(ax-1) + 4*(ax-1)*(ay-2) + (ay-1);

    int xspc = atomspace * xs;
    int yspc = atomspace * ys;

    int atomstart = atom_num;

    int x, y;
    for (y=0; y<ay; y++)
    {
        for (x=0; x<ax; x++)
        {
            SetAtom(&atoms[atom_num], agroup_num, size, mass, xp + x * xspc, yp + y * yspc, 0, 0);
            atompoints[atompoint_num].a = atom_num;
            atompoints[atompoint_num].u = (int)(((float)x / (float)(ax-1)) * 255);
            atompoints[atompoint_num].v = (int)(((float)y / (float)(ay-1)) * 255);
            atompoint_num++;
            atom_num++;

            if (x<ax-1)
            {
                if (y<ay-1)
                {
                    triangles[triangle_num].p0 = atomstart + y*ax + x;
                    triangles[triangle_num].p1 = atomstart + y*ax + x + 1;
                    triangles[triangle_num++].p2 = atomstart + (y+1)*ax + x;

                    triangles[triangle_num].p0 = atomstart + (y+1)*ax + x;
                    triangles[triangle_num].p1 = atomstart + y*ax + x + 1;
                    triangles[triangle_num++].p2 = atomstart + (y+1)*ax + x + 1;
                }

                if (y==0)
                {
                    SetBond(&bonds[bond_num++], atomstart + x, atomstart + x+1, atomspace, brk);
                    SetBond(&bonds[bond_num++], atomstart + x, atomstart + ax+x+1, sqrt(2)*atomspace, brk);
                    SetBond(&bonds[bond_num++], atomstart + x, atomstart + ax+x, atomspace, brk);
                }
                else if (y>0 && y<ay-1)
                {
                    SetBond(&bonds[bond_num++], atomstart + y*ax+x, atomstart + (y-1)*ax+x+1, sqrt(2)*atomspace, brk);
                    SetBond(&bonds[bond_num++], atomstart + y*ax+x, atomstart + y*ax+x+1, atomspace, brk);
                    SetBond(&bonds[bond_num++], atomstart + y*ax+x, atomstart + (y+1)*ax+x+1, sqrt(2)*atomspace, brk);
                    SetBond(&bonds[bond_num++], atomstart + y*ax+x, atomstart + (y+1)*ax+x, atomspace, brk);
                }
                else
                {
                    SetBond(&bonds[bond_num++], atomstart + y*ax+x, atomstart + (y-1)*ax+x+1, sqrt(2)*atomspace, brk);
                    SetBond(&bonds[bond_num++], atomstart + y*ax+x, atomstart + y*ax+x+1, atomspace, brk);
                };
            }
            else
            {
                if (y<ay-1)
                {
                    SetBond(&bonds[bond_num++], atomstart + y*ax+x, atomstart + (y+1)*ax+x, atomspace, brk);
                }
            }
        }
    }

    int i;
    for (i=b1; i<bond_num; i++)
    {
        atoms[bonds[i].atom1].nbonds++;
        atoms[bonds[i].atom2].nbonds++;
    }
    agroup_num++;
}


void RotateAtomGroup(int group, float xc, float yc, float r)
{
    vector c;
    c.x = xc;
    c.y = yc;

    vector v;
    vector *av;
    int i;
    for (i=0; i<atom_num; i++)
    {
        if (atoms[i].grp == group)
        {
			printf("ok");
            av = &atoms[i].pos;
            Vsub(av,&c,&v);
            Vrotate(&v,&v,r);
            Vadd(&v,&c,&v);
            Vset(av,&v);
        }
    }
}

void SetAtomGroupColor(int group, unsigned char r, unsigned char g, unsigned char b)
{
    int i;
    for (i=0; i<atom_num; i++)
    {
        if (atoms[i].grp == group)
        {
            SetAtomColor(&atoms[i], r, g, b);
        }
    }
}

void atom2blob(atom *a, blob *b)
{
    b->x = a->pos.x;
    b->y = a->pos.y;
    b->z = 1;
    b->a = a->col.a;
    b->r = a->col.r;
    b->g = a->col.g;
    b->b = a->col.b;
    b->size = a->size;
}

void testcreateagroup()
{
    CreateAtomBlock(2, 1.0, 360, -100, atomblockx, atomblocky, 1, 1);
    RotateAtomGroup(0, 0, 0, -0.5);
    SetAtomGroupColor(0, 191, 95, 255);
}

