#include <stdio.h>

#include "arg.h"
#include "common.h"
#include "crd_ut10xx.h"

static int
printf_dev_info(const char *prefix, CRD_UT10XX_t *ut)
{
	CRD_UT10XX_info_t *info = &(ut->info);
	const char *state;
	
	if (info->info & 0x04) state = "LOCK";
	else if (info->info & 0x02) state = "CONF";
	else if (info->info & 0x01) state = "INIT";
	else state = "CLEAR";
	
	printf("%sdevice state: %s\n", prefix, state);
	printf("%sdevice name: %s\n", prefix, info->name);
	printf("%sSO pin trys: %d\n", prefix, info->so_pin_trys);
	printf("%sUser pin trys: %d\n", prefix, info->user_pin_trys);
	printf("%sSO pin trys limit: %d\n", prefix, info->so_pin_limit);
	printf("%sUser pin trys limit: %d\n", prefix, info->user_pin_limit);
	printf("%ssoftware version: %d.%d\n", prefix, info->main_ver, info->sub_ver);
	printf("%savaliable memory: %d\n", prefix, info->public_mem);
	printf("%skeys limit: %d\n", prefix, info->keys_num);
	
	if (info->ecc_params)
		printf("%ssupported domains: %s\n", prefix, info->ecc_params->name);
	else
		printf("%ssupported domains: UNKNOWN\n", prefix);
	
	return (0);
}

static int
printf_key_info(const char *prefix, CRD_UT10XX_t *ut, int key)
{
	CRD_UT10XX_key_info_t *info = &(ut->keys[key]);
	
	int i;
	
	if (info->info & 0x01) 
	{
		printf("%skey state: GEN\n", prefix);
		printf("%skey name: %s\n", prefix, info->name);
		
		if (info->ecc_params)
		{
			printf("%skey domain: %s\n", prefix, info->ecc_params->name);
			printf("%spublic key:\n", prefix);
			printf("%s  :04\n%s  ", prefix, prefix);
			
			for (i = 0; i < info->ecc_params->field_octets; i++)
				printf(":%02X", (unsigned char)info->pub_x[i]);
				
			printf("\n%s  ", prefix);
			
			for (i = 0; i < info->ecc_params->field_octets; i++)
				printf(":%02X", (unsigned char)info->pub_y[i]);
				
			printf("\n");
		}
		else
			printf("%skey domain: UNKNOWN\n", prefix);
		
	}
	else
	{
		printf("%skey state: CLEAR\n", prefix);
	}
	
	return (0);
}

int
main(int argc, const char **argv)
{
	const char *help = 
		"\n\tinfo [-help] [-keys] [-devnum=num]\n\n"
		"\tThis programm prints information abaut devices connected to host.\n\n"
		"\t-help\n"
		"\t\tPrint this information.\n\n"
		"\t-keys\n"
		"\t\tIf this option is present, then programm displays information about\n"
		"\t\tdevices and its keys.\n\n"
		"\t-devnum\n"
		"\t\tThis option tells programm to list information only abaut device of\n"
		"\t\tspecified number. If is not used, then all devices are listed.\n\n";
	
	CRD_UT10XX_t *ut;
	
	int keys;
	int devnum = -1;
	
	int i;
	int j;
	
	if ( prologue(argv, help) )
		return (-1);
	
	if ( arg_getall(argv, "bi", "-keys", &keys, "-devnum", &devnum) < 0 )
		return (-2);
	
	if ((devnum > -1) && (CRD_UT10XX_find_by_index(devnum) == 0))
	{
		epilogue(stderr, "there is no device of that number\n", 0, 0);
		return (-3);
	}
	
	for (i = 0; ; i++)
	{
		if ((ut = CRD_UT10XX_find_by_index(i)) == 0)
			break;
		
		if ((devnum < 0) || (devnum == i))
		{
			printf("Device [%d][%s][%s]\n", i, ut->serial_number, ut->product_string);
			printf("  |-- Info\n");
			printf_dev_info("  |     ", ut);
			if (keys)
			{
				printf("  |\n");
				printf("  |-- Keys\n");
				for (j = 0; j < ut->info.keys_num; j++)
				{
					printf("  |     |-- Key [%d]\n", j);
					printf_key_info("  |     |     ", ut, j);
				}
			}
			printf("\n");
		}
	}
	
	return (epilogue(stderr, 0, 0, 0));
}
