/** \brief   A small tool to extract a list of particle IDs from an
 *           AHF_particles files.
 *
 * (C)  2009, S.R. Knollmann (steffen.knollmann@uam.es)
 */


/***********************************************************************
 *    Includes                                                         *
 ***********************************************************************/
#include "../version.h"
#include "../config.h"
#include <stdio.h>
#include <stdlib.h>
#include <inttypes.h>
#include <math.h>
#include <string.h>
#include "libutil/xmem.h"
#include "libutil/xstring.h"
#include "libutil/xfile.h"
#include "libutil/diediedie.h"


/***********************************************************************
 *    Global variables, used for the command line arguments            *
 ***********************************************************************/

/** The filename of the input data */
char *fInName;

/** The filename of the input data */
char *fOutName;

/** The filename with the list of the halos to select */
char *fSelectName;


/***********************************************************************\
 *    Definitions of local functions                                   *
 ***********************************************************************/
static void
local_parse_cmdline(int argc, char **argv);

static void
local_get_halolist(const char *fSelectName,
                   uint32_t   **haloIds,
                   uint32_t   *numHaloes);

static int
cmp_ids(const void *p1, const void *p2);


/***********************************************************************\
 *    MAIN                                                             *
 ***********************************************************************/
int
main(int argc, char **argv)
{
	uint32_t *haloIds;
	uint32_t numHaloes;
	uint32_t numParticlesInHalo;
	uint32_t id;
	uint32_t i, j, hit;
	int64_t tmp;
	FILE     *f, *fout;
  char    dummyline[2048];

	/* Do the command line stuff */
	local_parse_cmdline(argc, argv);

	/* Get the next haloes to select */
	local_get_halolist(fSelectName, &haloIds, &numHaloes);

	/* Open the particles file */
	f = xfopen(fInName, "r");
#ifdef STEFFEN
	fscanf(f, " %" SCNu32, &id);
#else
  fgets(dummyline,2048,f);
  sscanf(dummyline," %" SCNu32,&id);
#endif
  fprintf(stderr,"\ntotal number of haloes to scan: %"SCNu32"\n",id);

	/* Open output */
	fout = xfopen(fOutName, "w");

	/* Loop over all particles */
	hit = 0;
	fprintf(fout, "%" PRIu32 "\n", numHaloes);

	for (i = 0; i < haloIds[numHaloes - 1] + 1; i++) {
		/* Get the number of particles in this file */
#ifdef STEFFEN
		fscanf(f, " %" SCNu32, &numParticlesInHalo);
#else
    fgets(dummyline,2048,f);
    sscanf(dummyline," %" SCNu32,&numParticlesInHalo);
#endif
    fprintf(stderr," reading halo %"SCNu32" (%"SCNu32")\n", i,numParticlesInHalo);

		/* Do we want this one? */
		if (i == haloIds[hit]) {
      fprintf(stderr,"   found halo %"SCNu32"\n", i);
			fprintf(fout, "%" PRIu32 "\t%" PRIu32 "\n",
			        numParticlesInHalo, haloIds[hit]);
			hit++;
			for (j = 0; j < numParticlesInHalo; j++) {
#ifdef STEFFEN
#ifdef PARTICLES_INFO
				fscanf(f, " %" SCNi64 " %*i %*f", &tmp);
#else
				fscanf(f, " %" SCNi64, &tmp);
#endif
#else
        fgets(dummyline,2048,f);
        sscanf(dummyline," %" SCNi64,&tmp);
#endif
				id = (uint32_t)tmp;
				fprintf(fout, "%" PRIu32 "\n", id);
			}
		} else {
			for (j = 0; j < numParticlesInHalo; j++) {
#ifdef STEFFEN
#ifdef PARTICLES_INFO
				fscanf(f, " %" SCNi64 " %*i %*f", &tmp);
#else
				fscanf(f, " %" SCNi64, &tmp);
#endif
#else
        fgets(dummyline,2048,f);
        sscanf(dummyline," %" SCNi64,&tmp);
#endif
			}
		}
	}

	/* Done */
	xfclose(&fout);
	xfclose(&f);
	xfree(haloIds);
	xfree(fOutName);
	xfree(fSelectName);
	xfree(fInName);
#ifdef XMEM_TRACK_MEM
	xmem_info(stdout);
#endif
	return EXIT_SUCCESS;
} /* main */

/***********************************************************************\
 *    Implementation of local functions                                *
 ***********************************************************************/
static void
local_parse_cmdline(int argc, char **argv)
{
	/* Check for sufficient parameters */
	if (argc != 4) {
		fprintf(stderr,
		        "Usage: %s <particles file> "
		        "<halo selection file>"
		        "<outout file>\n\n",
		        argv[0]);
		exit(EXIT_FAILURE);
	}

	/* Get the input file name */
	fInName = xstrdup(argv[1]);

	/* Get the filename of the ID file */
	fSelectName = xstrdup(argv[2]);

	/* Get the filename of the output file */
	fOutName = xstrdup(argv[3]);

	/* Done */
	return;
} /* local_parse_cmdline */

static void
local_get_halolist(const char *fSelectName,
                   uint32_t   **haloIds,
                   uint32_t   *numHaloes)
{
	FILE     *f;
	uint32_t i;
  char     dummyline[2048];

	/* Open file */
	f = xfopen(fSelectName, "r");

#ifdef STEFFEN
	/* Get the number of haloes */
	if (fscanf(f, "%" SCNu32, numHaloes) != 1) {
		fprintf(stderr, "Could not read numHaloes.\n");
		diediedie(EXIT_FAILURE);
	}
#else
  fgets(dummyline,2048,f);
  sscanf(dummyline, "%" SCNu32, numHaloes);
#endif
  fprintf(stderr,"\n will grab the IDs of %"SCNu32" haloes:\n",*numHaloes);

	/* Get memory */
	*haloIds = xmalloc(sizeof(uint32_t) * *numHaloes);

	/* Get all IDs */
	for (i = 0; i < *numHaloes; i++) {
#ifdef STEFFEN
		if (fscanf(f, "%" SCNu32, (*haloIds) + i) != 1) {
			fprintf(stderr, "Could not read halo ID %" PRIu32 ".\n", i);
			diediedie(EXIT_FAILURE);
		}
#else
    fgets(dummyline,2048,f);
    sscanf(dummyline, "%" SCNu32, (*haloIds) + i);
    fprintf(stderr,"   %"SCNu32"\n",*((*haloIds) + i));
#endif
	}

	/* Sort the IDs */
	qsort((*haloIds), *numHaloes, sizeof(uint32_t), &cmp_ids);


	/* Clean */
	xfclose(&f);

	/* Done */
	return;
} /* local_get_halolist */

static int
cmp_ids(const void *p1, const void *p2)
{
	if (*((uint32_t *)p1) < *((uint32_t *)p2))
		return -1;

	if (*((uint32_t *)p1) > *((uint32_t *)p2))
		return 1;

	return 0;
}
