// $Id: newick.h,v 1.12 2018/01/03 21:33:03 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: Peter Beerli, Mary Kuhner, Jon Yamato and Joseph Felsenstein */


#ifndef NEWICK_H
#define NEWICK_H

#include <cassert>  // May be needed for inline definitions.
#include <string>
#include <vector>

#include "branch.h" // for Branch_ptr declaration

//------------------------------------------------------------------------------------

class Tree;

//------------------------------------------------------------------------------------

class UserTree
{
    // we accept the default ctor, copy-ctor, and operator=
  public:

    virtual ~UserTree() {};

    virtual bool Exists() { return false; };
    virtual void ToLamarcTree(Tree& stump) = 0;
};

//------------------------------------------------------------------------------------

class NullUserTree : public UserTree
{
    // we accept the default ctor, copy-ctor, and operator=
  public:

    virtual ~NullUserTree() {};

    virtual void ToLamarcTree(Tree&) { assert(false); }; // instantiating NULL tree
};

//------------------------------------------------------------------------------------

class NewickTree : public UserTree
{
  private:
    std::string m_newicktree;
    unsigned long m_curr_char;
    const std::string m_numbers;
    const std::string m_terminators;

    double ProcessLength();
    Branch_ptr ProcessName(const Tree& stump);
    void ProcessComment();  // currently throws comments away

    // we accept the default copy-ctor, and operator=

  public:

    NewickTree(const std::string& tree);
    virtual ~NewickTree() {};

    virtual bool Exists() { return true; };
    void ToLamarcTree(Tree& stump);  // not const due to use m_curr_char

};

//------------------------------------------------------------------------------------
// This is a helper class for NewickTree, representing one unfinished
// node in the tree.

class NewickNode
{
  private:

    Tree& m_tree;
    std::vector<NewickNode*> m_children;
    Branch_ptr m_branch;
    NewickNode* m_parent;
    double m_length;

    NewickNode(const NewickNode&); // not defined
    NewickNode& operator=(const NewickNode&);  // not defined

  public:
    NewickNode(Tree& stump);
    ~NewickNode();

    NewickNode* AddChild();
    NewickNode* Terminate();
    NewickNode* GetParent() const;
    Branch_ptr  GetBranch() const;
    void AddBranch(Branch_ptr br);
    void SetLength(double newlength);

    // recursively coalesce all nodes contained within this one,
    // returning the time (not length!) of coalescence.
    double Coalesce();  // not const because assigns to m_branch
}; // NewickNode

//------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------

class NewickConverter
{
  private:
    double RecurseWriteNewick(std::string& newick, Branch_ptr br) const;
    double RecurseWriteIntervalTreeNewick(std::string& newick, long site, Branch_ptr br) const;

    // We accept the default ctor, dtor, copy ctor and operator=
  public:
    std::string LamarcTreeToNewickString(const Tree& tree) const;
    std::string LamarcTreeToMSNewickString(const Tree& tree) const;

}; // NewickConverter

#endif // NEWICK_H

//____________________________________________________________________________________
