#ifndef UTILS2_H
#define UTILS2_H

#include <list>
#include <vector>
#include <set>
#include <map>
#include <string>
#include <iostream>
#include <fstream>
#include <cstdio>
#include <cstdlib>
//#include <limits>
using namespace std;

#include <sys/types.h>
#include <time.h>
#include <unistd.h>
#include <ctime>
#include "Utils.h"

// This file contains some extra utilties that are frequently used

// ***************************************************************************
// Common utilities
// ***************************************************************************
long GetCurrentTimeTick();
long GetElapseTime(long lastTime);
void GetCurrentCPUTime(std::clock_t &tmStart);
double GetElapseCPUTime(const std::clock_t &tmStart);
bool IsBoolArrayAllTrue( bool *bArray, int size);
void AppendIntVec(vector<int> &dest, const vector<int> &appending);
bool IsSetContainer(const set<int> &contianer, const set<int> &contained);
bool IsSetContainedInSets( const set<int> &s, const set< set<int> > &sets);
bool IsSetContainingOneOfSets( const set<int> &s, const set< set<int> > &sets ); 
void ConcatIntVec( vector<int> &vecAdded, const vector<int> & vecToAdd);
int ConvIntSetToPosition( const set<int> &s );
void ConvPositionToIntSet( int val, set<int> &s );
void PopulateSetWithInterval( set<int> &s, int left, int right);
void GetSeqInterval(const SEQUENCE &row, SEQUENCE  &rowIV,  int left, int right);
bool IsIntervalContained( const set<SEQUENCE> &seqs, int left, int right, const SEQUENCE &seqIV );
void SubtractSequenceSets( set<SEQUENCE> &s1, const set<SEQUENCE> &s2);
void DumpSequence( const SEQUENCE &seq);
void DumpVecSequences( const vector<SEQUENCE> &setSeqs );
void DumpSetSequences( const set<SEQUENCE> &setSeqs );
bool AreTwoInSameSet(int i1, int i2, const set< set<int> > &collections);
int GetItemIndexInVec( const vector<int> &vec, int item);
bool IsIntervalOverlap( const INTERVAL &iv1, const INTERVAL &iv2); 
bool GetIntervalOverlap( const INTERVAL &iv1, const INTERVAL &iv2, INTERVAL &ivBoth);
void GenerateRandBinVector(int sz, vector<int> &randVec);
bool IsBinary( int val);
void ReOrderWithRemovedSites( const vector<int> &posAfterRem, const vector<int> &removedPos, vector<int> &posBeforeRemove);
void GetSubsetVec(const vector<int> &vecOriginal, const set<int> &sitesToKeep, vector<int> &vecNew);
void AddMissingVecBits( vector<int> &rowComplete, const set<int> &sitesToAdd,  vector<int> &partialRow);

// ***************************************************************************
// Utilies for phasing
// ***************************************************************************
bool IsSequenceHaplotype( const SEQUENCE &seq);
bool IsSequenceGenotype( const SEQUENCE &seq);
bool CanPhaseGenoRow( const SEQUENCE &hap1, const SEQUENCE &hap2, const SEQUENCE &geno );
bool AreHapGenoRowCompatible( const SEQUENCE &hapRow, const SEQUENCE &genoRow, SEQUENCE *pComplement = NULL);
bool AreHapGenoRowsSame( const SEQUENCE &hapRow, const SEQUENCE &genoRow  );
bool IsTrivialRow( const SEQUENCE &row, SEQUENCE &resolved1, SEQUENCE &resolved2 );
bool IsHapSeqSmaller( const SEQUENCE &hapRow1, const SEQUENCE &hapRow2);
void CreateGenoRowFromHapRows( const SEQUENCE &hapRow1, const SEQUENCE &hapRow2,  SEQUENCE &genoRow);

// ***************************************************************************
// Utilies for hypercube related stuff
// ***************************************************************************
// We use the hypercube node index to access an hypercube node sequence
typedef int HCSequence;

void GetHyperCubeSeq(int hcSeq, SEQUENCE &seq, int hcWidth);
int GetHyperCubSeqBit( int hcSeq, int bit, int hcWidth);
int GetSeqIdFromSeq( const SEQUENCE &seq );
void FindNonSegSites( const set<HCSequence> &setSeqs, set<int> &sites , int dataWidth);
void FindNonSegSites( const set<SEQUENCE> &setSeqs, set<int> &sites, int dataLen );
int IsHCSeqsMutPair(  HCSequence seq1, HCSequence seq2, int dataWidth);
bool IsHCSeqsMutPairAt(  HCSequence seq1, HCSequence seq2, int dataWidth, int pos);
void MutateHCSeqAt( const HCSequence seq, HCSequence & res, int dataWidth, int mutPos );
bool IsHCSeqRecombinnable( HCSequence s1, HCSequence s2, HCSequence st, int dataWidth) ;
void RecombineHCSeqs( const HCSequence hcSeq1, const HCSequence hcSeq2, HCSequence &res, int dataWidth, int bkpt); 


#endif //UTILS2_H
