// $Id: gc_structures.h,v 1.40 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_STRUCTURES_H
#define GC_STRUCTURES_H

#include <set>
#include <map>
#include <vector>

#include "gc_dictionary.h"
#include "gc_file_info.h"
#include "gc_locus.h"
#include "gc_migration.h"
#include "gc_panel.h"
#include "gc_parent.h"
#include "gc_phase_info.h"
#include "gc_population.h"
#include "gc_structure_maps.h"
#include "gc_region.h"
#include "gc_trait.h"
#include "wx/string.h"

class gcTraitAllele;

class gcNameSet : public gcDictionary
{
  protected:
    virtual const wxString &    infoString() const;
  public:
    gcNameSet();
    virtual ~gcNameSet();
};

class gcTraitNameSet : public gcDictionary
{
  protected:
    virtual const wxString &    infoString() const;
  public:
    gcTraitNameSet();
    virtual ~gcTraitNameSet();
};

class GCStructures
{
  private:
    const GCDataStore * m_dataStoreP;
    gcNameSet           m_names;
    gcTraitNameSet      m_traitNames;
    gcBlockSetMap       m_blocks;
    gcRegionMap         m_regions;
    gcLocusMap          m_loci;
    gcPanelMap          m_panels;
    gcParentMap         m_parents;
    gcPopMap            m_pops;
    gcTraitMap          m_traitClasses;
    gcAlleleMap         m_alleles;
    gcPhenoMap          m_phenotypes;
    gcFileMap           m_files;
    gcMigrationMap      m_migrations;

    gcDisplayOrder      m_popDisplay;
    gcDisplayOrder      m_regionDisplay;

    bool                m_divergenceState;
    bool                m_panelsState;
    bool                m_divMigMatrixDefined;
    bool                m_migMatrixDefined;


  protected:
    bool                HaveBlocksForRegion(size_t regionId) const;
    bool                HaveBlocksForLocus(size_t locusId) const;
    bool                HaveBlocksForPop(size_t popId) const;
    bool                IsBlessedRegion(size_t locusId) const;
    bool                IsBlessedLocus(size_t locusId) const;
    bool                IsBlessedPop(size_t popId) const;

  public:
    GCStructures(const GCDataStore *);
    ~GCStructures();

    bool AnyZeroes() const;

    void AssignBlockToPop(size_t blockId, size_t popId);
    void AssignBlockToLocus(size_t blockId, size_t locusId);

    void AssignBlock(size_t blockId, size_t popId, size_t locusId);
    void AssignLocus(size_t locusId, size_t regionId);
    void AssignTrait(size_t traitId, size_t regionId);

    void AssignAllele(gcTraitAllele &, gcTraitInfo &);
    void AssignLocus(gcLocus &, gcRegion &);
    void AssignPhenotype(gcPhenotype &, gcTraitInfo &);
    void AssignTrait(gcTraitInfo &, gcRegion &);

    void RemoveBlockAssignment(size_t blockId);

    void DebugDump(wxString prefix=wxEmptyString) const;

    bool GetDivergenceState();
    bool GetDivergenceState() const;
    void SetDivergenceState(bool state);

    bool GetPanelsState();
    bool GetPanelsState() const;
    void SetPanelsState(bool state);

    bool GetDivMigMatrixDefined();
    bool GetDivMigMatrixDefined() const;
    void SetDivMigMatrixDefined(bool state);

    bool GetMigMatrixDefined();
    bool GetMigMatrixDefined() const;
    void SetMigMatrixDefined(bool state);

    gcIdSet     GetBlockIds(size_t popId, size_t locusId) const;
    gcIdSet     GetBlocksForLocus(size_t locusId) const;

    gcIdSet GetPanelIdsForRegions(gcIdSet regionIds) const;

    gcDisplayOrder  GetDisplayableLocusIds() const;
    gcDisplayOrder  GetDisplayablePopIds() const;
    gcDisplayOrder  GetDisplayableRegionIds() const;
    gcDisplayOrder  GetParentIds() const;

    objVector   GetDisplayableRegions() ;
    objVector   GetDisplayableLoci() ;
    objVector   GetDisplayableLociFor(size_t regionId) ;
    objVector   GetDisplayablePops() ;
    objVector   GetParents() ;

    constObjVector  GetConstDisplayableRegions()   const;
    constObjVector  GetConstDisplayableLoci()     const;

#if 0
    constObjVector  GetConstDisplayableLociFor(size_t regionId) const ;
#endif

    constObjVector  GetConstDisplayableLociInMapOrderFor(size_t regionId) const ;
    constObjVector  GetConstDisplayableLinkedLociInMapOrderFor(size_t regionId) const ;
    constObjVector  GetConstDisplayablePops()  const;
    constObjVector  GetConstParents()  const;

    constObjVector  GetConstTraits() const;

    gcIdVec         GetLocusIdsForRegionByCreation(size_t regionId) const;
    gcIdVec         GetLocusIdsForRegionByMapPosition(size_t regionId) const;

    gcTraitAllele &     GetAllele(size_t id);
    gcRegion &          GetRegion(size_t id);
    gcLocus &           GetLocus(size_t id);
    gcPhenotype &       GetPhenotype(size_t id);
    gcPopulation &      GetPop(size_t id);
    gcTraitInfo &       GetTrait(size_t id);
    gcPanel &           GetPanel(size_t id);
    gcParent &          GetParent(size_t id);
    gcMigration &       GetMigration(size_t id);

    const gcTraitAllele &   GetAllele(size_t id) const;
    const gcRegion &        GetRegion(size_t id) const;
    const gcLocus &         GetLocus(size_t id) const;
    const gcPhenotype &     GetPhenotype(size_t id) const;
    const gcPopulation &    GetPop(size_t id) const;
    const gcTraitInfo &     GetTrait(size_t id) const;
    const gcPanel &         GetPanel(size_t id) const;
    const gcPanel &         GetPanel(size_t regionId, size_t popId) const;
    const gcParent &        GetParent(size_t id) const;
    const gcMigration &     GetMigration(size_t id) const;
    const gcMigration &     GetMigration(size_t toId, size_t fromId) const;

    gcTraitAllele &             GetAllele(gcTraitInfo&,wxString name);
    gcTraitAllele &             GetAllele(wxString name);
    gcRegion &                  GetRegion(wxString name);
    gcLocus &                   GetLocus(gcRegion&,wxString name);
    gcLocus &                   GetLocus(wxString name);
    gcPhenotype &               GetPhenotype(wxString name);
    gcPopulation &              GetPop(wxString name);
    gcTraitInfo &               GetTrait(wxString name);
    gcPanel &                   GetPanel(wxString name);
    gcPanel &                   GetPanel(size_t regionId, size_t popId);
    gcParent &                  GetParent(wxString name);
    gcMigration &               GetMigration(wxString name);
    gcMigration &               GetMigration(size_t toId, size_t fromId);

    const gcTraitAllele &       GetAllele(wxString name) const;
    const gcRegion &            GetRegion(wxString name) const;
    const gcLocus &             GetLocus(wxString name) const;
    const gcPhenotype &         GetPhenotype(wxString name) const;
    const gcPopulation &        GetPop(wxString name) const;
    const gcTraitInfo &         GetTrait(wxString name) const;
    const gcPanel &             GetPanel(wxString name) const;
    const gcParent &            GetParent(wxString name) const;

    bool  HasParents() const;
    bool  HasPanel(size_t regionId, size_t popId) const;
    bool  HasBlock(size_t locusId, size_t popId) const;
    bool  HasMigration(size_t toId, size_t fromId) const;

    const GCPopMatcher &        GetPopMatcher(const GCFile&) const;
    const GCLocusMatcher &      GetLocusMatcher(const GCFile&) const;
    void                        SetPopMatcher(const GCFile&, const GCPopMatcher &);
    void                        SetLocusMatcher(const GCFile&, const GCLocusMatcher &);

    const gcPhenoMap &          GetPhenotypeMap() const;

    bool            HasAllele(wxString name) const;
    bool            HasLocus(wxString name) const;
    bool            HasPop(wxString name) const;
    bool            HasRegion(wxString name) const;
    bool            HasTrait(wxString name) const;
    bool            HasPanel(wxString name) const;
    bool            HasMigration(wxString name) const;

    long GetPopDisplayIndexOf(size_t popId) const;
    long GetLocusDisplayIndexOf(size_t locusId) const;

    size_t          GetPopForBlock(size_t blockId) const;
    size_t          GetLocusForBlock(size_t blockId) const;

    gcTraitAllele & FetchOrMakeAllele(gcTraitInfo&, wxString name);
    gcLocus &       FetchOrMakeLocus(gcRegion&, wxString name, const gcCreationInfo&);
    //gcPhenotype &   FetchOrMakePhenotype();
    gcPanel &       FetchOrMakePanel(wxString name);
    gcPopulation &  FetchOrMakePop(wxString name);
    gcRegion &      FetchOrMakeRegion(wxString name);
    gcTraitInfo &   FetchOrMakeTrait(wxString name);

    gcTraitAllele & MakeAllele(wxString name);
    gcRegion &      MakeRegion(wxString name=wxEmptyString,bool blessed=false);
    gcLocus &       MakeLocus(size_t regionId, wxString name, bool blessed, const gcCreationInfo&);
    gcLocus &       MakeLocus(gcRegion &, wxString name, bool blessed, const gcCreationInfo&);
    gcPhenotype &   MakePhenotype(wxString name=wxEmptyString);
    gcPopulation &  MakePop(wxString name=wxEmptyString, bool blessed=false);
    gcTraitInfo &   MakeTrait(wxString name);
    gcPanel &       MakePanel(wxString name, bool blessed, size_t regionId, size_t popId);
    gcParent &      MakeParent(wxString name);
    gcMigration &   MakeMigration(bool blessed, size_t toId, size_t fromId);

    gcPanel & CreatePanel(size_t regionId, size_t popId);

    void Rename(GCQuantum & object, wxString newName);

    bool RegionHasAnyLinkedLoci(size_t regionId) const;
    bool RegionHasAnyUnLinkedLoci(size_t regionId) const;

    void FragmentRegion(size_t regionId);
    void LocusToOwnRegion(size_t locusId);

    void MergeLoci(gcIdVec locusIds);
    void MergePops(gcIdVec popIds);
    void MergeRegions(gcIdVec regionIds);
    //void MergePanels(gcIdVec panelIds);

    void RemoveBlocks(gcIdSet blockIds);
    void RemoveBlocksForLocus(size_t locusId);
    void RemoveBlocksForPop(size_t popId);
    void RemoveRegion(gcRegion & region);
    void RemoveLocus(gcLocus & locus);
    void RemovePop(gcPopulation & pop);
    void RemoveRegions(objVector regions);
    void RemoveLoci(objVector loci);
    void RemovePops(objVector pops);
    void RemoveFile(size_t fileId);
    void RemovePanel(size_t regionId, size_t popId);
    void RemoveParent(size_t parentId);
    void RemoveParents();
    void RemoveMigration(size_t toId, size_t fromId);

    bool    GetFileSelection(size_t fileId) const;
    void    SetFileSelection(size_t fileId, bool selected);
    size_t  SelectedFileCount() const;
    void    AllFileSelectionsTo(bool selectValue);

    void AddFile(const GCFile &);
    bool HasUnparsedFiles() const;

    void SetParse(const GCParse & parse);
    void UnsetParse(const GCParse & parse);

    bool            HasParse(const GCFile &) const;
    const GCParse & GetParse(const GCFile &) const;
    const GCParse & GetParse(size_t fileId ) const;

    void    SetHapFileAdjacent( size_t fileId, size_t numHaps);
    bool    HasHapFileAdjacent(size_t fileId) const;
    size_t  GetHapFileAdjacent(size_t fileId) const;
    void    UnsetHapFileAdjacent(size_t fileId);

    bool    HasGenoFile(size_t fileId) const;
    void    UnsetGenoFile(size_t fileId);

    void    VerifyLocusSeparations(const gcRegion&) const;    // throws if not separated

    int GetPopCount();
    int GetPopCount() const;

    int GetParentCount();
    int GetParentCount() const;

    bool IsPop(size_t id);
    bool IsPop(size_t id) const;
    bool IsPop(wxString name);
    bool IsPop(wxString name) const;

    bool IsParent(size_t id);
    bool IsParent(size_t id) const;

    int GetUnusedPopCount();
    int GetUnusedPopCount() const;

    int GetUnusedParentCount();
    int GetUnusedParentCount() const;

    void ClearPopDisplayOrder();

    size_t FindTopParent();

    void MakeMigrationMatrix();
};

#endif  // GC_STRUCTURES_H

//____________________________________________________________________________________
