// $Id: gc_phase_info.h,v 1.13 2018/01/03 21:32:55 mkkuhner Exp $

/*
Copyright 2002-2005 Mary K. Kuhner, Peter Beerli, and Joseph Felsenstein

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

*/

/* Authors: Mary Kuhner, Jon Yamato, and Joseph Felsenstein */


#ifndef GC_PHASE_INFO
#define GC_PHASE_INFO

#include <map>
#include <set>

#include "gc_genotype_resolution.h"
#include "gc_phase.h"       // for gcUnphasedMarkers
#include "gc_phase_err.h"
#include "gc_set_util.h"
#include "gc_types.h"
#include "wx/arrstr.h"
#include "wx/string.h"

class gcPhaseInfo;

typedef std::map<wxString,gcUnphasedMarkers>    gcIndPhaseInfo;
typedef std::set<wxString>                      gcPhenotypeNames;

class gcPhaseRecord
{
    friend class gcPhaseInfo;

  private:
    gcPhaseSource       m_phaseSource;
    wxString            m_fileName;
    bool                m_hasLineNumber;
    size_t              m_lineNumber;
    wxString            m_individual;
    size_t              m_sampleCountIfNoSamples;
    wxArrayString       m_samples;
    gcIndPhaseInfo      m_unphasedInfo;
    gcIdSet             m_phenotypeIds;

  protected:
    void                SetLineNumber(size_t lineNumber);

  public:
    // best created with static methods below
    gcPhaseRecord();

    // not a virtual destructor -- we don't want these things
    // polymorphic
    // EWFIX.P3 -- WHY ???
    ~gcPhaseRecord();

    void                    AddPhenotypeId (size_t phenoId);
    const gcIdSet &         GetPhenotypeIds() const;
    void                    MergePhenotypeIds(const gcPhaseRecord&);

    gcPhaseSource           GetPhaseSource()    const;

    wxString                GetDescriptiveName()const;

    bool                    HasFileName()       const;
    const wxString &        GetFileName()       const;

    bool                    HasLineNumber()     const;
    size_t                  GetLineNumber()     const;

    bool                    HasIndividual()     const;
    const wxString &        GetIndividual()     const;

    bool                    HasSamples()        const;
    const wxArrayString &   GetSamples()        const;
    size_t                  GetSampleCount()    const;

    bool                    HasAnyZeroes()      const;

    void        AddUnphased(wxString locusName, const gcUnphasedMarkers & );
    bool                        HasUnphased(const wxString locusName) const;
    const gcUnphasedMarkers &   GetUnphased(const wxString locusName) const;
    wxArrayString               GetUnphasedLocusNames() const;

    bool operator==(const gcPhaseRecord&)       const;
    bool operator!=(const gcPhaseRecord&)       const;

    void    DebugDump(wxString prefix=wxEmptyString) const;

    static gcPhaseRecord MakeAdjacentPhaseRecord(   wxString        fileName,
                                                    size_t          lineNumber,
                                                    wxArrayString   samples);
    static gcPhaseRecord MakeAllelicPhaseRecord(    wxString        fileName,
                                                    size_t          lineNumber,
                                                    wxString        individualName,
                                                    size_t          numSamples);

    // ARGH! only this one is a pointer because in cmdParseIndividual
    // we need to make a bunch of them and then choose whether to use
    // or lose them all at once
    static gcPhaseRecord * MakeFullPhaseRecord(     wxString        fileName,
                                                    size_t          lineNumber,
                                                    wxString        individualName,
                                                    wxArrayString   sampleNames);
};

typedef std::pair<wxString,gcPhaseRecord>       recordPair;
typedef std::map<wxString,gcPhaseRecord>        stringToRecord;

class gcPhaseInfo
{
  private:
    stringToRecord      m_fromIndividual;
    stringToRecord      m_fromSample;

  protected:
    // returns true if new record was added
    bool    AddRecordIndividual (const gcPhaseRecord &);
    // returns true if new record was added
    bool    AddRecordSample     (const gcPhaseRecord &);

    // returns true if old record was replaced by new
    bool    MergeIndividualRecs (const gcPhaseRecord & curRec,
                                 const gcPhaseRecord & newRec);
  public:
    gcPhaseInfo();
    virtual ~gcPhaseInfo();

    void    AddRecord(const gcPhaseRecord&);
    void    AddRecords(const gcPhaseInfo &);

    void    RemoveRecord(const gcPhaseRecord&);

    bool                    HasIndividualRecord(wxString name)  const;
    const gcPhaseRecord &   GetIndividualRecord(wxString name)  const;

    bool                    HasSampleRecord(wxString name)      const;
    const gcPhaseRecord &   GetSampleRecord(wxString name)      const;

    void    DebugDump(wxString prefix=wxEmptyString) const;

    const stringToRecord &  GetIndividualRecords() const;

    bool    HasAnyZeroes() const;

};

#endif  // GC_PHASE_INFO

//____________________________________________________________________________________
