/***************************************************************************
 *   Copyright (C) 2007 by Faubet Pierre   *
 *   pierre.faubet@e.ujf-grenoble.fr   *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/

#ifndef MULTILOCUS_GENOTYPES_H
#define MULTILOCUS_GENOTYPES_H

#include <string>
#include <map>

using namespace std;

/**
 * Multilocus genotype data
 * @author Pierre Faubet <pierre.faubet@e.ujf-grenoble.fr>
 */
class multilocus_genotypes
  {
    /* Members */
  private:
    string inputfilename; /**< Name of the file with genetic data */

    int nbpop; /**< Number of populations */
    int nbloci; /**< Number of loci */
    int nballel; /**< Number of alleles per locus */
    int nbindiv; /**< Number of individuals */

    bool nodata,missingdata;
    int ***allelecount; /**< Number of alleles sampled from each subpopulation */
    bool **is_at_locus; /**< Check for presence of alleles at a given locus */

    int ***X; /**< Multilocus genotypes */
    int *S; /**< Subpopulations where individuals were sampled from */
    int *N; /**< Number of individuals sampled from each subpopulation */

    string *id; /**< Individuals' id */
    map<string,int> popnames; /**< id for populations */

    /**
     * Create arrays to store data
    */
    void createarrays();

    /**
     * Read genepop formated input file
     */
    void read_genepop_file(string filename);

    /**
     * Check for missing data
     */
    void checkdata();

    /* Methods */
  public:
    multilocus_genotypes();

    /**
    * Constructor
    * @param infilename Name of the file with genetic data
    */
    multilocus_genotypes(const string& infilename);

    ~multilocus_genotypes();

    /**
    * Print genetic data
    * @param outfil Name of the output file
    */
    void write(const string& outfil);

    /**
    * Return the number of alleles K
    * @return K
    */
    int get_nballel() const
      {
        return nballel;
      }

    /**
    * Return the number of individuals n
    * @return n
    */
    int get_nbindiv() const
      {
        return nbindiv;
      }

    /**
    * Get individuals' names
    * @param h individual
    * @return the idf for individual h
    */
    string get_id (int h) const
      {
        return id[h];
      }

    /**
    * Return the number of loci J
    * @return J
    */
    int get_nbloci() const
      {
        return nbloci;
      }

    /**
    * Return the number of subpopulations I
    * @return I
    */
    int get_nbpop() const
      {
        return nbpop;
      }

    /**
    * Return the name of the file with genetic data
    * @return inputfilename
    */
    string get_inputfilename() const
      {
        return inputfilename;
      }

    /**
    * Return allele i of inidividual h at locus j
    * @param h individual
    * @param j locus
    * @param i allele (0 or 1)
    * @return X_hji
    */
    int get_Xhji(int h,int j, int i) const
      {
        return X[h][j][i];
      }

    /**
    * Retunr the subpopulation where individual h were sampled from
    * @param h individual
    * @return S_h
    */
    int get_Sh(int h) const
      {
        return S[h];
      }

    /**
    * Return the number of individuals sampled from subpopulation q
    * @param q population
    * @return N_q
    */
    int get_Nq(int q) const
      {
        return N[q];
      }

    /**
    * Check if allele k is observed at locus j
    * @param j locus
    * @param k allele
    * @return true if allele k has been observed at locus j; false otherwise
    */
    bool get_is_at_locus(int j,int k) const
      {
        return is_at_locus[j][k];
      }

    /**
    * Check for missing data
    * @return true if missing genotypes are met
    */
    bool get_missingdata() const
      {
        return missingdata;
      }

    /**
    * @return true if there are no data
    */
    bool get_nodata() const
      {
        return nodata;
      }

    /**
    * Return the number of copies of allele k observed in subpopulation q at locus j
    * @param q population
    * @param j locus
    * @param k allele
    */
    int get_allelcount(int q,int j,int k) const
      {
        return allelecount[q][j][k];
      }
  };

#endif
