/*
   Copyright (c) 2015, Digi International Inc.

   Permission to use, copy, modify, and/or distribute this software for any
   purpose with or without fee is hereby granted, provided that the above
   copyright notice and this permission notice appear in all copies.

   THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
   WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
   MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
   ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
   WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
   ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
   OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/********************************************************************
	tcp_send.c

 	This sample program is used with Intellicom Series.

	This program and tcp_respond.c are to be executed on two different
	Intellicom boards so that the two boards communicate with each
	other.  In the absence of a second board, pcrespond.exe can be
	used on the PC console side at the command prompt. This executable
	and source code is located in "...\samples\icom\windows" directory.

	When a key on the keypad is pressed, a message associated with
	that key	is sent to a specified destination address and port.
	The destination then responds to that message.  The response is
	displayed to the LCD.

********************************************************************/
#class auto					/* Change local var storage default to "auto" */

/***********************************
 * Configuration                   *
 * -------------                   *
 * All fields in this section must *
 * be altered to match your local  *
 * network settings.               *
 ***********************************/

/*
 * Pick the predefined TCP/IP configuration for this sample.  See
 * LIB\TCPIP\TCP_CONFIG.LIB for instructions on how to set the
 * configuration.
 *
 * It is best to explicitly turn off DHCP in your configuration.  This
 * will allow the console to completely manage DHCP, so that it does
 * not acquire the lease at startup in sock_init() when it may not need
 * to (if the user has not turned on DHCP).
 */
#define TCPCONFIG 1

/*
 * 	Have TCP install text error messages when trouble occurs.  If not
 * 	defined, then TcpSocket.err_msg is not used at all.
 * 	TcpSocket.err_msg == NULL if none.
 */
#define _SOCKET_MESSAGES

/*
 * 	How many seconds to wait for active connection.
 */
#define  CONNECT_TIMEOUT	10

/*
 * Also note that you will need to set up the messages in the main()
 * function.
 */

/********************************
 * End of configuration section *
 ********************************/

#memmap xmem
#use "dcrtcp.lib"

// The structure that holds a message and the destination
typedef struct {
	char *text;
	char *addr;
	word port;
} Message;

#define IGNORE 99

/*
 * Send the message specified by the key value.  Note that the message
 * number is actually one less than the key number (since key number 0
 * cannot be used).
 */
void SendMessage(unsigned key, Message messageArray[])
{
	auto tcp_Socket	tcpSock;
	auto longword		remIP;
	auto int 			numBytes;
	auto char 			buffer[500];
	auto longword 		timeout;
	auto char *			p;
	auto int 			result;

	dispClear();
	remIP = inet_addr(messageArray[key-1].addr);
	tcp_open(&tcpSock, 0, remIP, messageArray[key-1].port, NULL);

	/* Wait for connection -- 10 seconds. */
	timeout = SEC_TIMER + CONNECT_TIMEOUT;
	while( !tcp_established(&tcpSock) ) {
		if( (long)(SEC_TIMER - timeout) >= 0 ) {
			dispPrintf( "ERROR: connect: timeout");
			// exit(99);
			return;
		}
		if( ! tcp_tick( (sock_type *) & tcpSock ) ) {
			dispPrintf( "ERROR: connect: %s\n", tcpSock.err_msg );
			// exit(99);
			return;
		}
	}

	/*  Write the message text, including the trailing NUL byte. */
	p = messageArray[key-1].text;
	for( numBytes = strlen(p)+1 ; numBytes > 0 ; 0 ) {
		result = sock_fastwrite( &tcpSock, p, numBytes );
		if( result < 0 || ! tcp_tick( (sock_type *) &tcpSock ) ) {
			dispPrintf( "ERROR: write: %s\n", tcpSock.err_msg );
			// exit( 99 );
			return ;
		}
		numBytes -= result;
		p += result;
	}

	dispPrintf("Message sent");

	/*  Wait for some data to appear, or an error... */
	while( 0 == (numBytes = sock_fastread(&tcpSock, buffer, sizeof(buffer))) ) {
		if( ! tcp_tick( &tcpSock ) ) {
	bad_read:
			dispPrintf( "ERROR: read: %s\n", tcpSock.err_msg );
			exit( 99 );
		}
	}
	dispClear();
	if (numBytes != -1) {
		buffer[numBytes] = '\0';
		dispPrintf("%s", buffer);
	} else {
		dispPrintf("Error");
	}
	sock_close(&tcpSock);
	while (tcp_tick(&tcpSock) != 0);
}

void main(void)
{
	Message 		messageArray[12];
	int 			i;
	unsigned 	key;	  // User keypress

	// Initialize the message array
	for (i = 0; i < 12; i++) {
		messageArray[i].text = "";
	}

	// Define messages here--note that you only need define the messages you
	// will actually use.  The IP addresses should NOT be MY_IP_ADDRESS !
	messageArray[0].text = "This is test 1.";
	messageArray[0].addr = "10.10.6.111";
	messageArray[0].port = 4040;

	messageArray[1].text = "This is test 2.";
	messageArray[1].addr = "10.10.6.111";
	messageArray[1].port = 4040;

	brdInit();
	sock_init();

	// Configure the upper row of keys on the keypad, in order from left
	// to right
	for (i = 0; i < 6; i++) {
		// Only enable a key if there is a corresponding message
		if (strcmp(messageArray[i].text, "") != 0) {
			keyConfig ( 5-i, i+1, 0, 0, 0, 0, 0 );
		} else {
			keyConfig ( 5-i, IGNORE, 0, 0, 0, 0, 0 );
		}
	}
	// Configure the lower row of keys on the keypad, in order from left
	// to right
	for (i = 6; i < 12; i++) {
		// Only enable a key if there is a corresponding message
		if (strcmp(messageArray[i].text, "") != 0) {
			keyConfig ( 19-i, i+1, 0, 0, 0, 0, 0 );
		} else {
			keyConfig ( 19-i, IGNORE, 0, 0, 0, 0, 0 );
		}
	}

	while (1) {
		costate {								//	Process Keypad Press/Hold/Release
			keyProcess ();
			waitfor ( DelayMs(10) );
		}

		costate {								//	Process Keypad Press/Hold/Release
			waitfor ( key = keyGet() );	//	Wait for Keypress
			if (key != IGNORE) {
				SendMessage(key, messageArray);
			}
		}
	}
}