// -*- Mode: C++; tab-width: 4 -*-

#include "asynchat.h"

class junk_lines_producer : public producer
{
  int n;
public:
  junk_lines_producer (int num_lines) : n(num_lines) { }
  string * more (void);
};

#ifdef _WIN32
#include <strstrea.h>
#else
#include <strstream.h>
#endif

string * 
junk_lines_producer::more (void)
{
  static char junk[] = "abcdefghijklmnopqrstuvwxyz0123456789\r\n";
  if (n) {
	// this just doesn't seem to work!
#if 0
	ostrstream * line = new ostrstream();
	*line << n << " " << junk << endl;
	n--;
	cerr << "line: " << line->pcount() << " bytes" << endl;
	string * ns = new string (line->str());
	return ns;
#endif
	n--;
	return new string (junk);
  } else {
	return new string;
  }
}

class junk_server : public dispatcher
{
  void handle_accept (void);
};

class junk_channel : public async_chat
{
  string input_buffer;

  void collect_incoming_data (const string& data);
  void found_terminator (void);
};

void
junk_server::handle_accept (void)
{
  struct sockaddr addr;
  int addr_len = sizeof(sockaddr);
  int fd = dispatcher::accept (&addr, &addr_len);
  cerr << "incoming connection" << endl;
  junk_channel * jc = new junk_channel;
  jc->set_fileno (fd);
  jc->set_terminator ("\r\n");
}

void
junk_channel::collect_incoming_data (const string& data)
{
  input_buffer.append (data);
  cerr << "collecting..." << endl;
}

void
junk_channel::found_terminator (void)
{
  // important to pass the length since input_buffer is not
  // zero-terminated
  if (input_buffer.length()) {
	istrstream s((char *)input_buffer.data(), input_buffer.length());
	int num = 0;
	s >> num;
	cerr << "found_terminator, n=" << num << " input_buffer.length() "<< input_buffer.length() << endl;
	// zero out the input buffer
	input_buffer.remove();
	if (num) {
	  send (new junk_lines_producer (num));
	} else {
	  close();
	}
  } else {
	close();
  }
}

#ifdef _WIN32
void init_winsock (void)
{
  WSADATA wd;
  WSAStartup (MAKEWORD (1,1), &wd);
}
#endif

int
main (int argc, char * argv[])
{
  junk_server js;
  int port = 8888;

#ifdef _WIN32
  init_winsock();
#endif

  if (argc < 2) {
	port = 8888;
  } else {
	port = atoi (argv[1]);
  }

  cerr << "create: " << js.create_socket (AF_INET, SOCK_STREAM) << endl;

  struct sockaddr_in addr;
  addr.sin_family = AF_INET;
  addr.sin_port = htons (port);
  addr.sin_addr.s_addr = htonl (INADDR_LOOPBACK);

  cerr << "bind: " << js.bind ((struct sockaddr *) &addr, sizeof (addr)) << endl;
  cerr << "listen: " << js.listen (5) << endl;

  dispatcher::loop(0);
  return 0;
}
