#ifndef __MISSING_H_
#define __MISSING_H_

#include <vector>
#include <utility>
#include <map>
#include <string.h>
#include "genotype.h"
#include "matrix.h"

using namespace std;


class Missing{
  // record all possible haplotype that is compatible with the observed genotype
 private:

  int *gcode;
  
  // enumerate all possible gcode that have the same missing patten as specified in missing_site
  vector<Genotype *> missing_pat_genotype;

  int count;
  int size;

  int ind_clus;
  int ind_1df;


 public:

  double **weight;  // demension dim * missing_pat_genotype.size(), row: haplotype; col: possible genotypes
  double *gfreq;  // dimension missing_pat_genotype.size()
  double **centmatrix;  // variance
  double **derivative;  // F_p
  double **derivative_clus;  // clustered haplotypes
  double **derivative_1df;  // 1-df test matrix
  vector<int> sites;  // record which row and column should be kept in the IQLS
  int dim;
  vector<int> nonzero;  // record the entry of missing_pat_genotype if at lest one weight is nonzero
  map<int, int> mapping_function;

  /* Constructor */
  Missing(const vector<int> & missing_site, const map<int, double> & hap_list, const vector<char *> & content, int size);

  void set_weight(map<pair<int, int>, double> & geno_freq_table, map<pair<int, int>, int> & hap_pair_map, int **count);
  void compute_centmatrix(double *freq, map<pair<int, int>, double> & geno_freq_table);
  void compute_derivative(map<int, double> & hap_freq_table, map<pair<int, int>, int> & hap_pair_map, int **count, double **rst);
  void compute_derivative_cluster(map<int, double> & hap_freq_table, double **mul_clus, int col_clus);
  void compute_derivative_1df(map<int, double> & hap_freq_table, double **mul_1df, int col_1df);
  void keep(const vector<int> & missing_site, const map<int, double> & hap_list, const vector<char *> & content);  // determin which row should be kept

  const vector<Genotype *> & get_missing_pat_genotype(){
    return missing_pat_genotype;
  }
  int *get_gcode(){
    return gcode;
  }
  int get_num(){
    return count;
  }
  void increase_num(){
    count++;
  }

  ~Missing();  // delete


 private:

  vector<int*> *complete_missing_genotype(int index=0);
  vector<int*> *complete_missing_haplotype(int *hcode, int index=0);
};


int find_element(const vector<int> & s_vec, int m);

#endif