#include "data-structure.h"
#include "vec.h"
#include "global-state.h"
#include <stdio.h>

extern FilesState LoadedFiles;

static void PUGS_Remove_imagefile_common ( Imagefile * im );

static void
PUGS_Remove_imagefile_common ( Imagefile * im )
{
	if ( im == NULL )
		return;

	SU_free( im->path );

	if ( im->hash != NULL )
		free(im->hash);
}

unsigned
PUDS_Get_valid_group_entries ( ImageGroup * grp, int leftcount, int rightcount )
{
	unsigned retvalue = 0;

	if ( grp == NULL )
		return retvalue;

	if ( grp->images.length == 0 )
		return retvalue;

	int len = grp->images.length;

	if ( leftcount < 0 || rightcount < 0 )
	{
		for ( int i = 0; i < len; ++i )
			if ( !grp->images.data[i]->disposed )
				retvalue++;

		return retvalue;
	}

	for ( int i = leftcount; i < len; ++i )
		for ( int k = ( i == leftcount ) ? rightcount : i + 1; k < len; ++k )
			if ( !grp->images.data[i]->disposed && !grp->images.data[k]->disposed && i < k)
				retvalue++;

	return retvalue;
}

void
PUDS_Add_imagefile_by_path ( char * path )
{
	Imagefile * im = calloc( 1, sizeof(Imagefile) );
	im->path = SU_simple(path);

	if ( vec_push( &LoadedFiles.images, im ) )
		fprintf( stderr, "Failed vec_push() in PUDS_Add_imagefile_by_path(%s)!\n", path );
}

void
PUDS_Remove_imagefile_main ( Imagefile * im )
{
	if ( im == NULL )
		return;

	PUGS_Remove_imagefile_common(im);
	vec_remove( &LoadedFiles.images, im );
	free(im);
}

void
PUDS_Remove_imagefile_group ( Imagefile * im )
{
	if ( im == NULL )
		return;

	PUGS_Remove_imagefile_common(im);
	vec_remove( &im->group->images, im );
	free(im);
}

void
PUDS_Create_group ( Imagefile * im1, Imagefile * im2, size_t hashlen )
{
	ImageGroup * grp = calloc( 1, sizeof(ImageGroup) );
	grp->hashlen = hashlen;
	vec_init(&grp->images);

	PUDS_Add_to_group( im1, grp );
	PUDS_Add_to_group( im2, grp );

	grp->hash = calloc( hashlen, sizeof(HASH64BIT) );
	memcpy( grp->hash, grp->images.data[0]->hash, hashlen );

	if ( vec_push( &LoadedFiles.groups, grp ) )
		fprintf( stderr, "Failed vec_push() in PUDS_Create_group()!!\n" );
}

void
PUDS_Add_to_group ( Imagefile * im, ImageGroup * grp )
{
	im->group = grp;
	if ( vec_push( &grp->images, im ) )
		fprintf( stderr, "Failed vec_push() in PUDS_Add_to_group()!!\n" );
}

void
PUDS_Remove_group ( ImageGroup * grp )
{
	{
		int i;
		Imagefile * item;
		vec_foreach_rev( &grp->images, item, i )
			PUDS_Remove_imagefile_group(item);
	}

	PUDS_Remove_group_only(grp);
}

void
PUDS_Remove_group_only ( ImageGroup * grp )
{
	if ( grp->hash != NULL )
		free(grp->hash);

	vec_deinit(&grp->images);
	vec_remove( &LoadedFiles.groups, grp );
	free(grp);
}

void
PUDS_Dispose ( void )
{
	{
		int i;
		ImageGroup * item;
		vec_foreach_rev( &LoadedFiles.groups, item, i )
			PUDS_Remove_group(item);
	}

	PUDS_Reset_directories();
	vec_clear(&LoadedFiles.dirs);
	vec_clear(&LoadedFiles.groups);
	vec_clear(&LoadedFiles.images);

	LoadedFiles.dupenum = 0;
	LoadedFiles.failedfiles = 0;
	LoadedFiles.hashedfiles = 0;
}

void
PUDS_Reset_directories ( void )
{
	int i;
	string * item;
	vec_foreach_rev( &LoadedFiles.dirs, item, i )
	{
		SU_free(item);
	}

	vec_clear(&LoadedFiles.dirs);
}
