/* FujiNetChat, an IRC client. Based on NetCat and the old FujiChat. */

/*
#define SELF "FujiNetChat"
#define VERSION "0.0"
#define BANNER SELF " v" VERSION " (B. Watson)\n"
*/

#include <atari.h>
#include <string.h>
#include "nio.h"
#include "irc.h"
#include "screen.h"
#include "edbox.h"
#include "config.h"
#include "kgetc.h"
#include "indic8.h"
#include "timers.h"

unsigned char err;              // error code of last operation.
unsigned char trip = 0;         // if trip == 1, fujinet is asking us for attention.
char old_enabled = 0;           // were interrupts enabled for old vector
void *old_vprced;               // old PROCEED vector, restored on exit.
unsigned int rxbuflen;        // RX buffer length
unsigned int txbuflen;          // TX buffer length
char reconnect_timeout = 1;

extern void ih();               // defined in intr.s

void txbuf_send(void) {
	/* don't send empty buffer */
	if(!txbuflen) return;

	/* always terminate with *ASCII* CRLF.
	   DO NOT USE '\n' or even '\x0a', cc65 turns it into $9b! */
	txbuf_append_chr(0x0d);
	txbuf_append_chr(0x0a);

	ind_net_tx();
	nwrite_txbuf();
	ind_net_idle();
	txbuf_init();
}

int fn_connect(void) {
	scr_display(SCR_SERVER);
	scr_print_current("Connecting to: ");
	scr_print_current(config.url);
	scr_eol_current();

	err = nopen();

	if(err != SUCCESS) {
		scr_print_current("Connection failed: ");
		print_errnum();
		scr_eol_current();
		bell();
		return 0;
	}

	// Open successful, set up interrupt
	old_vprced  = OS.vprced;     // save the old interrupt vector 
	old_enabled = PIA.pactl & 1; // keep track of old interrupt state
	PIA.pactl  &= (~1);          // Turn off interrupts before changing vector
	OS.vprced   = ih;            // Set PROCEED interrupt vector to our interrupt handler.
	PIA.pactl  |= 1;             // Indicate to PIA we are ready for PROCEED interrupt.

	reconnect_timeout = 1;

	return 1;
}

void fn_disconnect(void) {
	nclose();

	// Restore old PROCEED interrupt.
	PIA.pactl &= ~1; // disable interrupts
	OS.vprced=old_vprced; 
	PIA.pactl |= old_enabled; 
}

void init_channels(void) {
	char i;

	/* TODO: handle up to MAX_SCREENS when config.channels grows
	   past 5 elements. */
	for(i = 0; /* i < MAX_SCREENS - 2 */ i < 6; i++) {
		if(config.channels[i][0]) {
			scr_create(config.channels[i]);
		}
	}
}

void reconnect(void) {
	scr_display(SCR_SERVER);
	scr_print_current("Press a key");

	/* IMO, 0xff is easier to understand than KEY_NONE, here */
	OS.cdtmf3 = OS.ch = 0xff;

	if(reconnect_timeout) {
		OS.cdtmv3 = reconnect_timeout * timers.hz;
		scr_print_current(" or wait ");
		scr_cur_printnum(reconnect_timeout);
		scr_print_current(" sec");
		if(reconnect_timeout < 64)
			reconnect_timeout <<= 1;
	}
	scr_print_current(" to reconnect.\n");

	while(OS.cdtmf3 == 0xff && !keypress())
		/* NOP */;

	if(keypress()) kgetc();
}

void main(void) {
	bell_type = config.alert_type; /* TODO: have bell.s read staight from the struct */

	edbox_clear();

	#if 0
	scr_activate(0);
	scr_print_active("line one\n");
	scr_print_active("line two\n");
hang: goto hang;
	#else
	while(1) {
		if(fn_connect()) {
			ind_net_idle();
			irc_register();
			irc_loop();
		}
		OS.atract = 0;
		fn_disconnect();
		reconnect();
	}
	#endif
}
