// system headers
#include <stdio.h>
#include <stdlib.h>

// global VeriFinger SDK headers
#include <NCore.h>
#include <NTypes.h>
#include <NImages.h>
#include <FncMatcher.h>

char title[] = "Fingerprint identification tutorial, Version 6.0.0.0, Copyright (C) 2008 Neurotechnology\n";

int usage()
{
	printf("usage:\n");
	printf("\tIdentification <template_to_identify> <template> <template> ... \n");
	printf("\n");
	printf("\t<template_to_identify> - file name of extracted features to identify.\n");
	printf("\t<template> - file name of extracted features.\n");
	printf("\n\nExample:\n");
	printf("\tIdentification template_unknown.bin template1.bin template2.bin template3.bin\n");

	return 1;
}

static void printMatchDetails(FncmMatchDetails *matchDetails)
{
	printf("Matching score: ");
	if (matchDetails)
	{
		printf("%d", matchDetails->Score);
	}
	else
	{
		printf("0");
	}
	printf("\n");
}

int main(int argc, char **argv)
{
	NResult res = 0;
	int i;
	FILE * f1;
	FILE * f2;

	char * template_to_identify = NULL;
	long template_to_identify_size = 0;
	char ** templates = NULL;
	long * templates_sizes = NULL;
	FncmMatchDetails * matchDetails = NULL;
	int score;

	HFncMatcher matcher = NULL;

	printf(title);
	if (argc < 2)
	{
		return usage();
	}

	// opening first template file.
	// This template will matched against all other templates.

	f1 = fopen(argv[1], "rb");
	if (f1 != NULL)
	{
		fseek(f1, 0, SEEK_END);
		template_to_identify_size = ftell(f1);
		fseek(f1, 0, SEEK_SET);

		template_to_identify = malloc(template_to_identify_size);
		if (template_to_identify == NULL)
		{
			printf("Not enough memory.\n");
			fclose(f1);
			res = -1;
			goto exception_1;
		}
		fread(template_to_identify, 1, template_to_identify_size, f1);
		fclose(f1);
	}
	else
	{
		printf("Can't open file %s", argv[1]);
		res = -1;
		goto exception_1;
	}

	// opening other template files for identification.

	templates = malloc((argc - 2) * sizeof(char *));
	templates_sizes = malloc((argc - 2) * sizeof(long));

	for (i=2; i<argc; i++)
	{

		f2 = fopen(argv[i], "rb");
		if (f2 != NULL)
		{
			char * template_tmp;
			fseek(f2, 0, SEEK_END);
			templates_sizes[i-2] = ftell(f2);
			fseek(f2, 0, SEEK_SET);

			template_tmp = malloc(templates_sizes[i-2]);
			if (template_tmp == NULL)
			{
				printf("Not enough memory.\n");
				fclose(f2);
				res = -1;
				goto exception_2;
			}
			fread(template_tmp, 1, templates_sizes[i-2], f2);

			fclose(f2);

			templates[i-2] = template_tmp;
		}
		else
		{
			printf("Can't open file %s", argv[2]);
            res = -1;
			goto exception_2;
		}
	}
	res = FncmCreate(&matcher);
	if (res != N_OK)
	{
		printf("Failed to create matcher. Error %d\n", res);
		goto exception_3;
	}

	res = FncmIdentifyStart(matcher, template_to_identify, template_to_identify_size, &matchDetails);

	if (res != N_OK)
	{
		printf("Failed to start identify. Error %d\n", res);
		goto exception_4;
	}

	for (i=0; i<argc-2; i++)
	{
		res = FncmIdentifyNext(matcher, templates[i], templates_sizes[i], matchDetails, &score);
		if (res != N_OK)
		{
			printf("Failed to identify next. Error %d\n", res);
			goto exception_4;
		}
		printf("%d: Score = %d - ", i, score);
		if (score > 0)
		{
			printf ("matched\n");
			printMatchDetails(matchDetails);
		}
		else
		{
			printf ("not matched\n");
		}
	}

	res = FncmIdentifyEnd(matcher);

exception_4:
	if (matcher)
		FncmFree(matcher);
exception_3:
	if (templates)
	{
		for (i=0; i<argc-2; i++)
		{
			if (templates[i] != NULL)
				free(templates[i]);
		}
		free(templates);
	}
	if (templates_sizes)
		free(templates_sizes);

exception_2:
	if (template_to_identify) free(template_to_identify);
exception_1:
	return res;
}
