#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <ctype.h>

#include <sys/socket.h>

#include <linux/ax25.h>

#include "config.h"

/*
 *	Library routine for callsign conversion.
 *
 */
 
int convert_call_entry(char *name, char *buf)
{
	int ct   = 0;
	int ssid = 0;
	char *p  = name;

	while (ct < 6) {
		if (islower(*p))
			*p = toupper(*p);

		if (!isalnum(*p)) {
			printf("Invalid symbol in callsign.\n");
			return -1;
		}
		
		buf[ct] = (*p << 1);
		
		p++;
		ct++;
		
		if (*p == '-' || *p == 0)
			break;
	}

	while( ct < 6) {
		buf[ct] = ' ' << 1;
		ct++;
	}

	if (*p == 0) {
		ssid = 0;
	} else {
		p++;
		if (sscanf((char *)p, "%d", &ssid) != 1 || ssid < 0 || ssid > 15) {
			printf("SSID must follow '-' and be numeric in the range 0-15.\n");
			return -1;
		}
	}

	buf[6] = ((ssid + '0') << 1) & 0x1E;

	return 0;
}

int convert_call(char *call, struct full_sockaddr_ax25 *sax)
{

	int len = 0;
	char *bp, *np;
	char *addrp;
	int n = 0;
	char *tmp = strdup(call);
	
	if (tmp == NULL)
		return -1;
		
	bp = tmp;
	
	addrp = sax->fsa_ax25.sax25_call.ax25_call;

	do {
		/* Fetch one callsign token */
		while (*bp && isspace(*bp))
			bp++;

		np = bp;

		while (*np && !isspace(*np))
			np++;

		if (*np)
			*np++ = 0;
	
		/* Check for the optional 'via' syntax */
		if (n == 1 && (strcasecmp(bp, "V") == 0 || strcasecmp(bp, "VIA") == 0)) {
			bp = np;
			continue;
		}
		
		/* Process the token */
		if (convert_call_entry(bp, addrp) == -1) {
			free(tmp);
			return -1;
		}
			
		/* Move along */
		bp = np;
		n++;

		if (n == 1) {
			addrp  = sax->fsa_digipeater[0].ax25_call;	/* First digipeater address */
			len   += sizeof(struct sockaddr_ax25);
		} else {
			addrp += sizeof(ax25_address);
			len   += sizeof(ax25_address);
		}
	} while (n < AX25_MAX_DIGIS && *bp);

	free(tmp);

	/* Tidy up */
	sax->fsa_ax25.sax25_ndigis = n - 1;
	sax->fsa_ax25.sax25_family = AF_AX25;	

	return len;
}

int convert_call_arglist(char *call[], struct full_sockaddr_ax25 *sax)
{

	int len = 0;
	char *bp;
	char *addrp;
	int n = 0;
	int argp = 0;

	addrp = sax->fsa_ax25.sax25_call.ax25_call;

	do {
		/* Fetch one callsign token */
		if ((bp = call[argp++]) == NULL)
			break;
	
		/* Check for the optional 'via' syntax */
		if (n == 1 && (strcasecmp(bp, "V") == 0 || strcasecmp(bp, "VIA") == 0))
			continue;
		
		/* Process the token */
		if (convert_call_entry(bp, addrp) == -1)
			return -1;
			
		n++;

		if (n == 1) {
			addrp  = sax->fsa_digipeater[0].ax25_call;	/* First digipeater address */
			len   += sizeof(struct sockaddr_ax25);
		} else {
			addrp += sizeof(ax25_address);
			len   += sizeof(ax25_address);
		}
	}
	while (n < AX25_MAX_DIGIS && call[argp]);

	/* Tidy up */
	sax->fsa_ax25.sax25_ndigis = n - 1;
	sax->fsa_ax25.sax25_family = AF_AX25;	

	return len;
}
