// $Id: Converter_LamarcDS.h,v 1.23 2018/01/03 21:32:56 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: Patrick Colacurcio, Peter Beerli, Mary Kuhner, Jon Yamato 
/* Authors: Patrick Colacurcio, Peter Beerli, Mary Kuhner, Jon Yamato 
and Joseph Felsenstein */


// LamarcDS is a representation of the found seen in a Lamarc Datafile
// Each lamarcDS has the following information.
// Most of it is currently default.
// double coalescenceStartValues;
// method_type coalescenceMethod;   // changed from string to method_type by ewalkup

// MARY ADDS:
// double migrationStartValues;
// method_type migrationMethod; // changed from string to method_type by ewalkup
// long migrationMaxEvents;

// long coalescenceMaxEvents;
// long replicates;
// double temperatures;
// double swapInterval;  // I have no idea what this is.
// double resimulating;
// long initialNumber;
// long initialSamples;
// long initialDiscard;
// long initialInterval;
// long finalNumber;
// long finalSamples;
// long finalDiscard;
// long finalInterval;
// string verbosity;
// string echo;
// string profile;
// string posterior;
// long seed;
// string outputFile;
// string summaryFile;

// Oh yeah.  It also has some regions containing population data.
// No two regions will have the same name.  If no name is given, give it a
// unique name. The unique name will be in the format 'Region XXXX' where 'X'
// is a capital letter. Every region in a single 'LamarcDS' must have the same
// populations.  Even if those  populations are empty.  If a new region is
// added, every region in the Datastore will then have the union of the old
// populations and the new populations.  In most cases, these newly created
// populations will be empty, but apparently it helps the program just knowing
// that  these populations exist.

// Some notes on some methods.

// validateRegionName(const string&) will make sure the region name is not
// just whitespace or empty string.  If it is, a unique name is provided for
// the region.

// string getUniqueName() will provide unique names for regions that are
// provided without a name.  The Name will look like 'Region XXXX' where X
// is a capital letter tween A and Z.

// doesRegionNameExist(const string&) will return true if the region name
// exists withing this datasource.  False otherwise.

// validateNewRegion(RegionDS&) malongains constralong longegrity through
// ensuring that every region in a datasource always has the same set of
// populations.

#ifndef CONVERTER_LAMARCDS_H
#define CONVERTER_LAMARCDS_H

#include <map>
#include <string>

#include "Converter_DataSourceIf.h"
#include "Converter_RegionDS.h"
#include "Converter_types.h" // for map typedefs

using std::string;

class LamarcDS : public DataSourceIf
{
  private:
    double m_coalescenceStartValues;
    method_type m_coalescenceMethod;
    long m_coalescenceMaxEvents;

    // MARY
    double m_migrationStartValues;
    method_type m_migrationMethod;
    long m_migrationMaxEvents;

    long m_replicates;
    double m_temperatures;
    double m_swapInterval;  // I have no idea what this is.
    double m_resimulating;
    long m_initialNumber;
    long m_initialSamples;
    long m_initialDiscard;
    long m_initialInterval;
    long m_finalNumber;
    long m_finalSamples;
    long m_finalDiscard;
    long m_finalInterval;
    string m_verbosity;
    string m_progverbosity;
    string m_echo;
    string m_profile;
    string m_posterior;
    long m_seed;
    string m_outputFile;
    string m_inSummaryFile;
    string m_outSummaryFile;
    bool   m_useInSummaryFile;
    bool   m_useOutSummaryFile;

    RegionMap m_regions;

    // destroy the stored genetic data, used by ReorderUsing()
    void EraseRegions();

    // Validation for LamarcDS
    void validateRegionName(RegionDS& region) const;
    string getUniqueName() const;
    void validateNewRegion(RegionDS& region);

  public:
    //  Note.  Constructors may throw ConverterBaseError's
    LamarcDS();                                // starts with no regions.  huh.
    LamarcDS(RegionDS& region);
    virtual ~LamarcDS();

    //  get an iterator to the regions contained by this lamarc datasource.
    RegionMap::iterator getFirstRegion();
    RegionMap::const_iterator getFirstRegion() const;

    //  get an iterator to the end of the region list.
    RegionMap::iterator getLastRegion();
    RegionMap::const_iterator getLastRegion() const;

    //  add an region
    void addRegion (RegionDS& region);

    //  Merge an existing LamarcDS to this LamarcDS
    //  TODO:  Figure whether the lamarc ref passed should be const.
    void mergeTo(LamarcDS& lamarc);

    //  Reorder the internal data maps according to the given map
    //  Provided for use in the UI.  An InvalidSequenceLengthError
    //  can be thrown, potentially aborting the whole process, no
    //  internal cleanup is performed in this case.
    void ReorderUsing(RegByPopMap newmap);

    //  get the number of regions contained by the LamarcDS
    long numRegions() const;

    //  get the total number of population units contained by
    //  the LamarcDS, used by the UI
    long GetNUnits() const;

    //  originally part of private validation, pulled out for use by
    //  the SpaceConverter to validate the spacing info
    bool doesRegionNameExist(const string& name) const;

    //  is a non-contiguous type of genetic data present?
    bool HasNonContiguousData() const;

    //  are SNPs present in the stored genetic data?
    bool HasSNPs() const;

    //  A whole bunch of methods that allow our dear user to
    //  set the <forces> information.

    void setCoalescenceStartValues(const double);
    void setCoalescenceMethod(method_type);
    void setCoalescenceMaxEvents(const long);
    void setReplicates(const long);  // unsigned?
    void setTemperatures(const double);
    void setSwapInterval(const long);  // unsigned
    void setResimulating(const double);
    void setInitialNumber(const long);  // unsigned?
    void setInitialSamples(const long);  // unsigned?
    void setInitialDiscard(const long);  // unsigned?
    void setInitialInterval(const long);  // unsigned?
    void setFinalNumber(const long);  // unsigned?
    void setFinalSamples(const long);  // unsigned?
    void setFinalDiscard(const long);  // unsigned?
    void setFinalInterval(const long);  // unsigned?
    void setVerbosity(const string&);  // restrictions?
    void setProgVerbosity(const string&);  // restrictions?
    void setEcho(const string&);  // boolean?
    void setProfile(const string&);
    void setPosterior(const string&);
    void setSeed(const long);
    void setOutputFile(const string&);
    void setInSummaryFile(const string&);
    void setOutSummaryFile(const string&);

    string getXML(unsigned int numTabs) const;   //  From DataSourceIf
};

#endif // CONVERTER_LAMARCDS_H

//____________________________________________________________________________________
