#ifndef _MCIO_
#define _MCIO_

#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <unistd.h>
#include <math.h>

#include <vsubs.h>
#include <admutils.h>

#define MAXSTR 512
#define LONGSTR 10000
#define MAXFF  50
#define MAXCH  100
#define MTCHROM 90
#define XYCHROM 91
#define BADCHROM 99
#define GDISMUL 1000000
// multiplier for gdis to make integer for sort

enum outputmodetype
{
  ANCESTRYMAP,
  EIGENSTRAT,
  PED,
  PACKEDPED,
  PACKEDANCESTRYMAP
};


typedef struct
{
  char ID[IDSIZE];
  double gpos;
  double ppos;
  int chrom;
  char cchrom[6];
  int nn[4];
  int ignore;
  int isrfake;
  char alleles[2];
  int inputrow;
  int cuptnum;
  int chimpfudge;
} SNPDATA;


int numfakes (SNPDATA ** snpraw, int *snpindx, int nreal, double spacing);
double nextmesh (double val, double spacing);
double interp (double l, double r, double x, double al, double ar);

int
loadsnps (SNP ** snpm, SNPDATA ** snpraw,
	  int *snpindx, int nreal, double spacing, int *numignore);

int readsnpdata (SNPDATA ** snpraw, char *fname);
int readinddata (Indiv ** indivmarkers, char *fname);
int readindpeddata (Indiv ** indivmarkers, char *fname);
void pedname (char *name, char *sx0, char *sx1);

int readtldata (Indiv ** indivmarkers, int numind, char *fname);
int readindval (Indiv ** indivmarkers, int numind, char *fname);
int readfreqdata (SNP ** snpm, int numsnps, char *fname);
void clearsnp (SNP * cupt);
int rmindivs (SNP ** snpm, int numsnps, Indiv ** indivmarkers, int numindivs);
int rmsnps (SNP ** snpm, int numsnps, char *deletesnpoutname);
void clearind (Indiv ** indm, int numind);
void cleartg (Indiv ** indm, int nind);

double mknn (int *nn, int n0, int n1);
void clearsnpord ();
int getsnps (char *snpfname, SNP *** snpmarkpt, double spacing,
	     char *badsnpname, int *nignore, int numrisks);
int getsizex (char *fname);
int getindivs (char *indivfname, Indiv *** indmarkpt);

int setstatus (Indiv ** indm, int numindivs, char *smatch);
int setstatusv (Indiv ** indm, int numindivs, char *smatch, int val);

long getgenos (char *genoname, SNP ** snpmarkers, Indiv ** indivmarkers,
	       int numsnps, int numindivs, int nignore);
void getgenos_list (char *genotypelist, SNP ** snpmarkers,
		    Indiv ** indivmarkers, int numsnps, int numindivs,
		    int nignore);
void printsnps (char *snpoutfilename, SNP ** snpm, int num, Indiv ** indm,
		int printfake, int printvalids);
int checkxval (SNP * cupt, Indiv * indx, int val);
void printdata (char *genooutfilename, char *indoutfilename,
		SNP ** snpm, Indiv ** indiv, int numsnps, int numind,
		int packmode);
int readgdata (Indiv ** indivmarkers, int numind, char *gname);
int numvalidind (Indiv ** indivmarkers, int numind);
int numvalidgtind (SNP ** snpm, int numsnps, int ind);
int numvalidgt (Indiv ** indivmarkers, SNP * cupt);
int numvalidgtx (Indiv ** indivmarkers, SNP * cupt, int affst);
int getweights (char *fname, SNP ** snpm, int numsnps);
void outpack (char *genooutfilename, SNP ** snpm, Indiv ** indiv, int numsnps,
	      int numind);
int ispack (char *gname);
int iseigenstrat (char *gname);
void inpack (char *genooutfilename, SNP ** snpm, Indiv ** indiv, int numsnps,
	     int numind);
int inpack2 (char *genooutfilename, SNP ** snpm, Indiv ** indiv, int numsnps,
	     int numind);
int ineigenstrat (char *genooutfilename, SNP ** snpm, Indiv ** indiv,
		  int numsnps, int numind);
void setepath (SNP ** snpm, int n);
void clearepath (char *xpack);
long bigread (int fdes, char *packg, long numbytes);

// pedfile support
int getpedgenos (char *genoname, SNP ** snpmarkers, Indiv ** indivmarkers,
		 int numsnps, int numindivs, int nignore);
void genopedcnt (char *genoname, int **gcounts, int nsnp);

int pedval (char *sx);
int xpedval (char c);
int ptoachrom (char *ss);

void setgref (int **gcounts, int nsnp, int *gvar, int *gref);
void cleargdata (SNP ** snpmarkers, int numsnps, int numindivs);
void setgenotypename (char **gname, char *iname);
void settersemode (int mode);

void dobadsnps (SNPDATA ** snpraw, int nreal, char *badsnpname);
int snprawindex (SNPDATA ** snpraw, int nreal, char *sname);
int readsnpmapdata (SNPDATA ** snpraw, char *fname);
int checkfake (char *ss);
void setbadpedignore ();
int setsdpos (SNPDATA * sdpt, int pos);

void
outeigenstrat (char *snpname, char *indname, char *gname,
	       SNP ** snpm, Indiv ** indiv, int numsnps, int numind);

void
outped (char *snpname, char *indname, char *gname,
	SNP ** snpm, Indiv ** indiv, int numsnps, int numind, int ogmode);

void
outpackped (char *snpname, char *indname, char *gname, SNP ** snpm,
	    Indiv ** indiv, int numsnps, int numind, int ogmode);

void setbedbuff (char *buff, int *gtypes, int numind);
int bedval (int g);
int str2chrom (char *ss);

void outindped (char *indname, Indiv ** indiv, int numind, int ogmode);

void printmap (char *snpname, SNP ** snpm, int numsnps, Indiv ** indiv);

int maxlinelength (char *fname);
int checksize (int numindivs, int numsnps, enum outputmodetype outputmode);

void setomode (enum outputmodetype *outmode, char *omode);

void
outfiles (char *snpname, char *indname, char *gname, SNP ** snpm,
	  Indiv ** indiv, int numsnps, int numind, int packem, int ogmode);

void snpdecimate (SNP ** snpm, int nsnp, int decim, int mindis, int maxdis);
void decimate (SNP ** cbuff, int n, int decim, int mindis, int maxdis);
int vvadjust (double *cc, int n, double *pmean);
int killhir2 (SNP ** snpm, int numsnps, int numind, double physlim,
	      double genlim, double rhothresh);
void freecupt (SNP ** cupt);
void freeped ();
void cntpops (int *count, Indiv ** indm, int numindivs, char **eglist,
	      int numeg);
void printalleles (SNP * cupt, FILE * fff);
char *getpackgenos ();
void clearpackgenos ();
void setchr (int mode);
void setchimpmode (int mode);

int genoopenit (genofile ** gfile, char *geno2name, SNP ** snp2m,
		Indiv ** indiv2m, int numsnp2, int numindiv2, int nignore);
int genoreadit (genofile * gfile, SNP ** pcupt);
void genocloseit (genofile * gfile);

void putped (int num);
void getped (int num);

void logdeletedsnp (char *snpname, char *cmnt, char *deletesnpoutname);
void sortsnps (SNP ** snpa, SNP ** snpb, int n);
void setpordercheck (int mode);
void putsnpordered (int mode);
int getsnpordered ();


#endif
