with Ada.Text_IO; use Ada.Text_IO;
with Ada.Integer_Text_IO; use Ada.Integer_Text_IO;
with GNAT.Sockets; use GNAT.Sockets;
with signals; use signals;
with Ada.Containers.Vectors;
with Handlers; use Handlers;
with Constants; use Constants;
with Dispatchers; use Dispatchers;

procedure server is

    HOST    : constant String := "localhost";
    PORT    : constant Port_Type := 6666;
    work    : Boolean := True;
    address : Sock_Addr_Type;
    server  : Socket_Type;
    socket  : Socket_Type;
    h2      : Sigint_Handler;
    status  : Gnat.Sockets.Selector_Status;
    selector: signals.selector_Access;
    req     : Request_Type(Non_Blocking_IO);
begin
    Put_Line("start of server");
    Dispatcher.Start;
    selector := new Gnat.Sockets.Selector_Type;
    h2.selector(selector);
    Gnat.Sockets.Create_Selector(selector.all);
    address.Addr := Addresses (Get_Host_By_Name(host), 1);
    address.Port := PORT;

    Create_Socket(server);
    Set_Socket_Option (
        server,
        Socket_Level,
        (Reuse_Address, True));

    Bind_Socket (server, address);
    Put_Line("Binded");
    Listen_Socket(server);
    Put_Line("Listening");

    loop
        Put_Line("Waiting to accept");
        Accept_Socket (
                       Server => server,
                       Socket => socket,
                       Address => address,
                       Timeout => GNAT.Sockets.Forever,
                       Selector => selector,
                       Status => status);
        exit when status =  Gnat.Sockets.Aborted;
        Put_Line("Accepted");

        Control_Socket(socket, req);

        Dispatcher.dispatch(socket);
        Put_Line("Handled by listener");

    end loop;

    Gnat.Sockets.Close_Selector(selector.all);
    Close_Socket (server);

    Dispatcher.Stop;

    Put_Line("end of server");
end server;