/*
 * asmail is the AfterStep mailbox monitor
 * Copyright (c) 2002 Albert Dorofeev <albert@tigr.net>
 * For the updates see http://www.tigr.net/
 *
 * This software is distributed under GPL. For details see LICENSE file.
 */

#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <unistd.h>
#include <string.h>

#include "globals.h"
#include "imap.h"
#include "socklib.h"

#define BYE(RET_STATUS) { \
	Sclose(s); \
	return(RET_STATUS); \
}

#define WAITOK {					\
    switch (Sread(s->sd, input, MAX_INPUT_LENGTH, mb->timeout)) {	\
        case -1:	/* Error */			\
	   BYE(STAT_CONN);				\
        case 0:		/* Timeout */			\
           BYE(STAT_TIMEOUT);				\
    }							\
}

int imap_mailcheck( struct mbox_struct * mb ) {
	SOCKET * s;
	char input[MAX_INPUT_LENGTH+1];
	char output[MAX_INPUT_LENGTH+1];
	char key[MAX_INPUT_LENGTH+1];
	int ctotal = 0;
	int cnew = 0;
	char * tmp_str;
	int tmp_int;
	int unseen_supported = 0;

	if ( !( s = Sopen() ) ) {
		return STAT_FAIL;
	}
	if ( Sclient(s, mb->server, mb->port) == -1 ) {
		BYE(STAT_CONN);
	}
	/* Once we connect, we should receive the greeting */
	WAITOK;
	if ( strncmp(input, "* OK", 4) ) {
		BYE(STAT_CONN);
	}
	/* Login into the server */
	sprintf(output, "A000 LOGIN %s %s\r\n", mb->user, mb->pass);
	if ( Swrite(s->sd, output) == -1 ) {
		BYE(STAT_CONN);
	}
	WAITOK;
	if ( strncmp(input, "A000 OK", 7) ) {
		BYE(STAT_LOGIN);
	}
	/* seems we are logged in, get statistics */
	sprintf(output, "A001 STATUS %s (MESSAGES)\r\n", mb->mbox);
	if ( Swrite(s->sd, output) == -1 ) {
		BYE(STAT_CONN);
	}
	WAITOK;
	if ( strncmp(input, "* STATUS", 8) ) {
		BYE(STAT_CONN);
	}
	if ( tmp_str = strstr(input, "MESSAGES") ) {
		sscanf(tmp_str, "MESSAGES %d", &ctotal);
	} else {
		printf("asmail: imap_mailcheck: did not get MESSAGES in response to the STATUS.\n");
		BYE(STAT_FAIL);
	}
	WAITOK;
	if ( strncmp(input, "A001 OK", 7) ) {
		BYE(STAT_CONN);
	}
	sprintf(output, "A002 STATUS %s (UNSEEN)\r\n", mb->mbox);
	if ( Swrite(s->sd, output) == -1 ) {
		BYE(STAT_CONN);
	}
	WAITOK;
	if ( strncmp(input, "* STATUS", 8) ) {
		BYE(STAT_CONN);
	}
	if ( tmp_str = strstr(input, "UNSEEN") ) {
		sscanf(tmp_str, "UNSEEN %d", &cnew);
	} else {
		printf("asmail: imap_mailcheck: did not get UNSEEN in response to the STATUS.\n");
		BYE(STAT_FAIL);
	}
	WAITOK;
	if ( strncmp(input, "A002 OK", 7) ) {
		BYE(STAT_CONN);
	}
	/* and good-bye */
	sprintf(output, "A004 LOGOUT\r\n");
	if ( Swrite(s->sd, output) == -1 ) {
		BYE(STAT_CONN);
	}
	WAITOK;
	if ( strncmp(input, "* BYE", 5) ) {
		BYE(STAT_CONN);
	}
	Sclose(s);
	if ( (mb->cnew != cnew) && (cnew != 0) ) {
		pthread_mutex_lock(&mb->mutex);
		mb->flags |= FLAG_ARRIVED;
		pthread_mutex_unlock(&mb->mutex);
	}
	mb->cnew = cnew;
	mb->ctotal = ctotal;
	return(STAT_IDLE);
}

void imap_handle( struct mbox_struct * mb ) {
	/* Sanity check */
	if ( mb->type != MBOX_IMAP ) {
		printf("asmail: imap_handle: Cowardly refusing to work with a non-IMAP server.\n");
		mb->status = STAT_FAIL;
		pthread_exit(NULL);
	}
	if ( ! strlen(mb->server) ) {
		printf("asmail: imap_handle: no server name specified!\n");
		mb->status = STAT_FAIL;
		pthread_exit(NULL);
	}
	if ( ! strlen(mb->user) ) {
		printf("asmail: imap_handle: no user name specified!\n");
		mb->status = STAT_FAIL;
		pthread_exit(NULL);
	}
	if ( mb->port == 0 ) 
		mb->port = PORT_IMAP;
	if ( ! strlen(mb->mbox) )
		strcpy(mb->mbox, IMAP_MAILBOX_DEFAULT);
	while (1) {
		mb->status |= STAT_RUN;
		signal_update();

		if ( ! ( mb->status = imap_mailcheck(mb) ) ) {
			mb->status = STAT_IDLE;
			if ( mb->cnew > 0)
				mb->mail = MAIL_NEW;
			else if ( mb->ctotal > 0 )
				mb->mail = MAIL_OLD;
			else
				mb->mail = MAIL_NONE;
		}
		signal_update();
		sleep_check(mb->update);
	}
}

