#include "common/fusebox.h"
#include "common/packet.h"
#include "common/utils.h"
#include "common/lattice.h"
#include "common/act_type.h"
#include "common/actors/simple_room.h"

Fusebox fb;
Lattice l(40,40);

void send_lattice(int connection)
{
    Atom *a;
    Electron *e;
    
    Packet_info_vect::write_to(fb[connection], ACTOR_SYSTEM,
			       0, 0, l.get_w(), l.get_h());

    for (int i = 0; i < l.get_w(); i++)
    {
	for (int j = 0; j < l.get_h(); j++)
	{
	    for (int list = 0; list < LIST_LAST; list++)
	    {
		a = l.get(i,j);

		if (a)
		{
		    a->get(list).reset();
		    
		    while ((e = (Electron *)a->get(list).get_next()))
		    {
			warning("sending atom (%d, %d)", i, j);
			Packet_command::write_to(fb[connection],
						 e->actor_type,
						 e->actor_id,
						 COMMAND_FROM_TO,
						 -1, -1, i, j);
		    }
		}
	    }
	}
    }
}

int game_loop()
{
    int	new_connection;

    Packet const *p;

    new_connection = fb.check_new_connection();

    if (new_connection >= 0)
	send_lattice(new_connection);
    
    for (int i = 0; i < fb.get_nr_plugs(); i++)
    {
	if (fb[i])
	{
	    p = read_packet_static(fb[i]);
	    
	    if (p)
	    {
		if (p->err)
		{
		    warning("pulling plug %d from the socket", i);
		    fb.close_connection(i);
		}
		else
		{
		    print_packet(p);
		    if (p->get_type() == TYPE_INFO_STRING)
		    {
			if (!strcmp(((Packet_info_string *)p)->get_string(), "quit"))
			{
			    // pull the plug
			    warning("quit requested: pulling plug %d", i);
			    fb.close_connection(i);
			}
			if (!strcmp(((Packet_info_string *)p)->get_string(), "shutdown"))
			{
			    // shutdown the server
			    warning("shutdown requested by plug %d", i);
			    return 0;
			}
		    }
		}
	    }
	}
	
	usleep(10000);
    }

    return 1;
}

void add_room(int x, int y, int actor_id)
{
    Atom *a = new Atom;
    Simple_room *sr = new Simple_room(actor_id);
    
    a->add(sr);
    l.set(a, x, y);
}

int main(int argc, char **argv)
{
    progname = argv[0];

    // initialize the lattice
    for (int i = 0; i < 38; i++)
    {
	add_room(i + 1, 1, i);
    }
	
    for (int i = 0; i < 38; i++)
    {
	add_room(i + 1, 38, 38 + i);
    }

    for (int i = 0; i < 36; i++)
    {
	add_room(1, i + 2, 76 + i);
    }
    
    for (int i = 0; i < 36; i++)
    {	
	add_room(38, i + 2, 112 + i);
    }

    add_room(10,20,200);
    add_room(10,19,201);
    add_room(10,18,202);
    add_room(10,17,203);
    add_room(10,16,204);
    add_room(11,17,205);
    add_room(12,18,206);
    add_room(13,17,207);
    add_room(14,16,208);
    add_room(14,17,209);
    add_room(14,18,210);
    add_room(14,19,211);
    add_room(14,20,212);
    
    while (game_loop());
    
    return 0;
}
