#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include <getopt.h>

typedef enum
{
	MIPL_DEBUG_LEVEL_NONE = 0,
	MIPL_DEBUG_LEVEL_RXL,
	MIPL_DEBUG_LEVEL_RXL_RXD,
	MIPL_DEBUG_LEVEL_TXL_TXD,
} MIPL_DEBUG_LEVEL_E;

typedef unsigned short uint16;

typedef unsigned uint32;

typedef struct
{
	bool boot;
	bool encrypt;
	MIPL_DEBUG_LEVEL_E debug;
	uint16 port;
	uint32 keep_alive;
	size_t uri_len;
	char* uri;
	size_t ep_len;
	char* ep;
} MIPL_T;

void usage( const char *name )
{
	printf( "Usage: %s [OPTION]\r\n", name );
	printf( "Launch a client.\r\n" );
	printf( "Options:\r\n" );
	printf( "-b BOOT\t\tSet the bootstrap mode of the client.Default: 0\r\n" );
	printf( "-d DEBUG\tSet the debug mode of the client.Default: 0\r\n" );
	printf( "-e ENCRYPT\tSet the encrypt of the client.\r\n" );
	printf( "-i URI\t\tSet the coap uri of the server to connect to. For example: coap://localhost:5683\r\n" );
	printf( "-n NAME\t\tSet the endpoint name[imei;imsi] of the client.\r\n" );
	printf( "-p PORT\t\tSet the local port of the client to bind to. Default: srand\r\n" );
	printf( "-t TIME\t\tSet the lifetime of the client. Default: 300\r\n" );
	printf( "\r\n" );
}

void output_buffer(unsigned char *buffer, int length,int index, int flag)
{
	int i = 0;
	while ( i < length )
	{
		printf( "%02X", buffer[i++] );
	}
	printf(",%d,%d\r\n",index,flag);
}

void mipl_generate(char *buf, size_t buflen, MIPL_T *mipl)
{
	uint32 offset = 0;
	int mipl_num = 0;
	memset(buf, 0, buflen);

	char mode = ((mipl->boot & 0x1) << 4) | (mipl->encrypt & 0x1);
	memcpy(buf + offset, &mode, 1);
	offset++;
	memcpy(buf + offset, &mipl->debug, 1);
	offset++;
	memcpy(buf + offset, &mipl->port, 2);
	offset += 2;
	memcpy(buf+offset, &mipl->keep_alive, 4);
	offset += 4;

	memcpy(buf + offset, &mipl->uri_len, 2);
	offset += 2;
	memcpy(buf + offset, mipl->uri, mipl->uri_len);
	offset += mipl->uri_len;
	memcpy(buf + offset, &mipl->ep_len, 2);
	offset += 2;
	memcpy(buf + offset, mipl->ep, mipl->ep_len);
	offset += mipl->ep_len;

	mipl_num = 0;
	while(offset > 1024)//每条+MIPLCONF命令最多输入1024字节配置数据
	{
		printf("AT+MIPLCONF=%d,",1024);
		output_buffer( (unsigned char *)(buf + (mipl_num >> 10)),1024,mipl_num + 1,0);//index从1起始
		mipl_num++;
		offset -= 1024;
	}
	printf("AT+MIPLCONF=%d,",offset);
	output_buffer( (unsigned char *)(buf + (mipl_num >> 10)),offset,mipl_num + 1,1);//结束
}

int main(int argc, char *argv[])
{
	char conf[1024];
	MIPL_T mipl;
	
	char* const short_options = "i:p:t:n:d:b:e:h";
	char c;
	struct option long_options[] =
	{
		{"uri", 1, NULL, 'i'},
		{"port", 1, NULL, 'p'},
		{"keep_alive", 1, NULL, 't'},
		{"ep", 1, NULL, 'n'},
		{"debug", 1, NULL, 'd'},
		{"boot", 1, NULL, 'b'},
		{"encrypt", 1, NULL, 'e'},
		{"help", 0, NULL, 'h'},
		{0, 0, 0, 0},
	};

	while((c = getopt_long (argc, argv, short_options, long_options, NULL)) != -1)
	{
		switch (c)
		{
		case 'i':
		{
			mipl.uri = optarg;
			mipl.uri_len = strlen(optarg);
		}
		break;

		case 'p':
		{
			mipl.port = atoi(optarg);
		}
		break;

		case 't':
		{
			mipl.keep_alive = atoi(optarg);
		}
		break;

		case 'n':
		{
			mipl.ep = optarg;
			mipl.ep_len = strlen(optarg);
		}
		break;

		case 'd':
		{
			mipl.debug = atoi(optarg);
		}
		break;

		case 'b':
		{
			mipl.boot = atoi(optarg);
		}
		break;

		case 'e':
		{
			mipl.encrypt = atoi(optarg);
		}
		break;
		case 'h':
		usage(argv[0]);
		break;
		}
	}

	mipl_generate(conf,sizeof(conf),&mipl);
}
