// $Id: gc_datastore.h,v 1.100 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_DATASTORE_H
#define GC_DATASTORE_H

#include "gc_file.h"
#include "gc_locus_err.h"
#include "gc_structures.h"
#include "gc_types.h"
#include "wx/string.h"

class gcExportable;
class gcNameResolvedInfo;
class GCGenotypeResolution;
class GCIndividual;
class gcRegion;
class GCLocusMatcher;
class GCParseSample;
class gcPhenotype;
class GCPopMatcher;
class gcLocus;
class gcTraitInfo;
class GCSequentialData;
class gcUnphasedMarkers;
class TiXmlDocument;
class TiXmlElement;

class GCDataStore
// Everything we need to know to run the converter should
// be stored here. (Or possibly everything we need to undo/redo
// and put other stuff in another structure?)
{
  private:
    dataFileSet                     m_dataFiles;
    gcPhaseInfo                     m_phaseInfo;
    wxString                        m_commandFileCurrentlyBeingParsed; // EWFIX ugh!
    wxString                        m_commentString;
    wxString                        m_outfileName;
    GCStructures                    m_structures;

  protected:
    /////////////////////////////////////////////////
    // Parse munging
    /////////////////////////////////////////////////
    GCParse *       OneParse(GCFile &,GCFileFormat,gcGeneralDataType,GCInterleaving);
    GCParseVec *    AllParsesForFile(GCFile &);
    void            MungeParses(GCParseVec &);
    GCParseVec      GoodPhylipParses(GCFile & file);
    GCParseVec      GoodMigrateParses(GCFile & file, gcGeneralDataType);
    /////////////////////////////////////////////////

    /////////////////////////////////////////////////
    // for building TiXml DOM tree
    /////////////////////////////////////////////////
    TiXmlElement *  MakeBlockElem(const gcLocus & locusRef, bool requireMapPosition) const;
    TiXmlElement *  MakeBlockElemWithMapPosition(const gcLocus & locusRef ) const;
    TiXmlElement *  MakeBlockElemWithoutMapPosition(const gcLocus & locusRef ) const;
    void AddDataBlockElem(TiXmlElement * sampleElem, const GCSequentialData &, const gcLocus & locusRef ) const;
    void AddDataBlockElem(TiXmlElement * sampleElem, const GCSequentialData &, const gcLocus & locusRef, size_t siteIndex ) const;
    void AddDefaultPhaseElem(TiXmlElement * individualElem) const;
    void AddPhaseElem(TiXmlElement *, const GCIndividual &, const gcLocus & ) const;
    void AddPopulationElemForRegion(TiXmlElement *, const gcNameResolvedInfo &, const gcRegion &,const gcPopulation&) const;
    TiXmlElement *  MakePopulationElemForUnlinkedLocus(const gcNameResolvedInfo &, const gcPopulation&, const gcRegion &, const gcLocus &, size_t indexInLocus) const;
    void AddRegionElem(TiXmlElement * dataElem, const gcExportable &, const gcRegion &) const;
    void AddEffectivePopSizeElem(TiXmlElement * regionElem, const gcRegion &) const;
    void AddSampleElem(TiXmlElement * individualElem, const GCIndividual &, const gcRegion&, size_t hapIndex) const;
    void AddSampleElem(TiXmlElement * individualElem, const GCIndividual &, const gcRegion&, const gcLocus &, size_t siteIndex, size_t hapIndex) const;
    void AddSpacingElem(TiXmlElement * regionElem, const gcRegion&) const;
    TiXmlElement *  MakeSpacingElemMulti(const constObjVector & loci) const;
    // TiXmlElement *  MakeSpacingElemSingle(const gcLocus &) const;
    void AddTraitsElem(TiXmlElement * regionElem, const GCTraitInfoSet &) const;
    void AddGenoResolutionElem(TiXmlElement * individualElem, const gcPhenotype &) const;
    void AddIndividualElem(TiXmlElement * popElem, const GCIndividual&, const gcRegion &) const;
    void AddIndividualElem(TiXmlElement * popElem, const GCIndividual&, const gcRegion &, const gcLocus&, size_t siteIndex) const;
    void AddPanelElem(TiXmlElement * popElem, const gcPanel&) const;
    TiXmlElement *  MakeUnlinkedSite(const gcExportable &, const gcRegion &, const gcLocus &, size_t index) const;
    std::vector<TiXmlElement*>  MakeUnlinkedRegionElems(const gcExportable &, const gcRegion&) const;
    void AddDivergenceElem(TiXmlElement * divergenceElem) const;
    void AddDivergenceMigrationElem(TiXmlElement * divergenceElem) const;
    void AddMigrationElem(TiXmlElement * migrationElem);

    wxString        MakeUnlinkedName(wxString regionName, size_t siteIndex) const;

    gcUnphasedMarkers * CheckPhaseMarkers(const gcUnphasedMarkers *,
                                          wxString individualName,
                                          const gcLocus & locusRef,
                                          bool anyZeroes) const;

    /////////////////////////////////////////////////
    // for parsing cmd file
    /////////////////////////////////////////////////
    void                    cmdParseBlock(TiXmlElement *, gcRegion&, size_t numBlocksInRegion);
    void                    cmdParseComment(TiXmlElement *);
    void                    cmdParseDivergence(TiXmlElement *);
    void                    cmdParseDivergences(TiXmlElement *);
    gcPhaseRecord *         cmdParseIndividual(TiXmlElement *, wxString fileName);
    void                    cmdParseIndividuals(TiXmlElement *, wxString fileName);
    void                    cmdParseInfile(TiXmlElement *);
    void                    cmdParseInfiles(TiXmlElement *);
    void                    cmdParseOutfile(TiXmlElement *);
    gcPhenotype &           cmdParsePhenotype(TiXmlElement *);
    void                    cmdParsePanel(TiXmlElement *);
    void                    cmdParsePanels(TiXmlElement *);
    void                    cmdParsePopulation(std::map<wxString,int> &,TiXmlElement *);
    void                    cmdParsePopulations(TiXmlElement *);
    void                    cmdParseRegion(TiXmlElement *);
    void                    cmdParseRegions(TiXmlElement *);
    void                    cmdParseSpacing(TiXmlElement *, gcRegion&);
    void                    cmdParseTrait(std::map<wxString,int> &,TiXmlElement *);
    void                    cmdParseTraitLocation(TiXmlElement *, gcRegion&);
    void                    cmdParseTraits(TiXmlElement *);
    GCLocusMatcher          makeLocusMatcher(TiXmlElement *);
    GCPopMatcher            makePopMatcher(TiXmlElement *);
    gcPhenotype &           cmdParseGenoResolution(TiXmlElement *);

  public:
    GCDataStore();
    virtual ~GCDataStore();

    virtual void NukeContents();

    //////////////////////////////////////////////////////////////
    // error and warning messages
    //////////////////////////////////////////////////////////////
    virtual void        GCFatal             (wxString msg) const;
    virtual void        GCFatalBatchWarnGUI (wxString msg) const;
    virtual void        GCFatalUnlessDebug  (wxString msg) const;
    virtual void        GCError             (wxString msg) const;
    virtual void        GCWarning           (wxString msg) const;
    virtual void        GCInfo              (wxString msg) const;

    virtual void    fileRejectingError      (wxString msg,size_t lineNo) const;
    virtual void    batchFileRejectGuiLog   (wxString msg,size_t lineNo) const;
    virtual void    warnLog                 (wxString msg) const;
    virtual void    warnLog                 (wxString msg,size_t lineNo) const;

    virtual bool    guiQuestionBatchLog     (wxString msg,wxString stopButton, wxString continueButton) const;

    //////////////////////////////////////////////////////////////
    // generic data manipulation
    //////////////////////////////////////////////////////////////
    void    Rename(GCQuantum& object, wxString name);

    //////////////////////////////////////////////////////////////
    // data file methods
    //////////////////////////////////////////////////////////////
    GCFile &                    AddDataFile(wxString fullPathFileName);
    GCFile &                    AddDataFile(wxString fullPathFileName,GCFileFormat,gcGeneralDataType,GCInterleaving);
    void                        AssignParseLocus(const GCParseLocus &, gcLocus &);
    bool                        CanAssignParseLocus(const GCParseLocus &, const gcLocus &) const;
    void                        AssignPop(const GCParsePop &, gcPopulation &);
    size_t                      GetDataFileCount() const;
    const GCParseBlock *        GetParseBlock(size_t blockId) const;
    constBlockVector            GetBlocks(size_t popId, size_t locusId) const;
    constBlockVector            GetBlocksForLocus(size_t locusId) const;
    GCFile &                    GetDataFile(size_t fileId);
    const GCFile &              GetDataFile(size_t fileId) const;
    const dataFileSet &         GetDataFiles() const;

    bool                        FileInducesHaps(size_t fileId) const;

#if 0
    void                        AddHapFile(wxString fullPathFileName);
#endif

    locVector                   GetLociFor(const GCParse &, const GCLocusMatcher &);
    popVector                   GetPopsFor(const GCParse &, const GCPopMatcher &);
    size_t                      GetSelectedDataFileCount() const;
    bool                        HasNoDataFiles() const;
    bool                        HasUnparsedFiles() const;
    void                        RemoveDataFile(GCFile & fileRef);
    void                        RemoveFiles(bool selectedOnly);
    void                        SelectAllFiles();
    void                        SetSelected(const GCFile &,bool selected);
    void                        SetSelected(const gcLocus &,bool selected);
    void                        SetParseChoice( const GCParse &,
                                                const GCPopMatcher &,
                                                const GCLocusMatcher &);
    void                        UnsetParseChoice(const GCParse &);
    void                        UnselectAllFiles();

#if 0
    void                AddMapFile(wxString fullPathFileName);
    void                AddMapFileAsXml(wxString fullPathFileName);
    void                AddMapFileAsOldFormat(wxString fullPathFileName);
#endif

    const GCParse&            GetParse(size_t parseId) const ;
    const GCParse&            GetParse(const GCFile&) const ;
    const GCParse&            GetParse(const GCFile&, size_t index) const ;
    bool                GetSelected(const GCFile&) const;
    bool                HasParse(const GCFile&) const;

    gcGeneralDataType   GetLegalLocusTypes(size_t locusId) const;

    //////////////////////////////////////////////////////////////
    // trait methods
    //////////////////////////////////////////////////////////////

    gcTraitInfo &       AddNewTrait(wxString name);

    //////////////////////////////////////////////////////////////
    // other methods
    //////////////////////////////////////////////////////////////

    void            DebugDump(wxString prefix=wxEmptyString) const;

    gcExportable        BuildExportableData() const;
    void                ThrowLocusWithoutDataType(wxString locusName, wxString regionName) const;
    bool                FillExportInfo(gcNameResolvedInfo &, gcPhaseInfo &) const;
    bool                AddLocusData(GCIndividual&,const gcLocus&,GCParseSample&) const;
    bool                AddLocusData(GCIndividual&,const gcLocus&,GCParseSample&, const wxArrayString & sampleNames) const;
    GCIndividual &      makeOrFetchInd(wxString name,std::map<wxString,GCIndividual*> &, gcNameResolvedInfo&) const;
    TiXmlDocument *     ExportFile();
    void                WriteExportedData(TiXmlDocument *);
    int                 ProcessCmdFile(wxString fileName);

    gcPhaseInfo *       BuildPhaseInfo(bool carpIfBroken=true) const;
    void                DiagnosePhaseInfoProblems(const gcPhaseInfo&) const;
    bool                PhaseInfoHasAnyZeroes() const;

    void SetLamarcCommentString (wxString commentString);
    wxString    GetOutfileName() const ;
    void SetOutfileName     (wxString outFileName);

    bool    NeedsDataFor(const gcPopulation & , const gcLocus &) const;

    const GCStructures & GetStructures() const ;
    GCStructures & GetStructures()       ;

    TiXmlElement *      CmdExportGenoReso(const gcPhenotype &) const;
    TiXmlElement *      CmdExportIndividuals() const;
    TiXmlElement *      CmdExportInfile(const GCFile &) const;
    TiXmlElement *      CmdExportLocus(const gcLocus &) const;
    TiXmlElement *      CmdExportPhenotype(const gcPhenotype &) const;
    TiXmlElement *      CmdExportPop(const gcPopulation &) const;
    TiXmlElement *      CmdExportRegion(const gcRegion &) const;
    TiXmlElement *      CmdExportSegment(const gcLocus &) const;
    TiXmlElement *      CmdExportTrait(const gcTraitInfo &) const;
    TiXmlDocument *     ExportBatch() const;
    void                WriteBatchFile(TiXmlDocument*,wxString fname);

    virtual void    GettingBusy(const wxString&) const;
    virtual void    LessBusy(const wxString&) const;
};

#endif  // GC_DATASTORE_H

//____________________________________________________________________________________
