////////////////////////////////////////////////////////////////////////////////
// 
// TriangNode.hh 
//
//    produced: 30/04/98 jr
//
////////////////////////////////////////////////////////////////////////////////
#ifndef TRIANGNODE_HH
#define TRIANGNODE_HH

#include <assert.h>

#include "LabelSet.hh"
#include "SimplicialComplex.hh"

#include "CommandlineOptions.hh"

#include "Chirotope.hh"
#include "Symmetry.hh"
#include "Flip.hh"

namespace topcom {

  class TriangNode : public SimplicialComplex {
  private:
    int            _ID;
    parameter_type _no;
    parameter_type _rank;
    mutable bool   _valid;
  public:

    // constructors:
    TriangNode();
    inline TriangNode(const TriangNode&);
    inline TriangNode(TriangNode&&);
    inline TriangNode(const int, // ID
		      const parameter_type, // no
		      const parameter_type, // rank
		      const SimplicialComplex&, // simplicial complex
		      const bool = true); // satisfies output predicate?
    inline TriangNode(const int, // ID
		      const parameter_type, // no
		      const parameter_type, // rank
		      SimplicialComplex&&, // simplicial complex
		      const bool = true); // satisfies output predicate?
    inline TriangNode(const int, // ID
		      const TriangNode&);
    inline TriangNode(const int, // ID
		      const TriangNode&, 
		      const Flip&, // flip to flip
		      const bool = true); // satisfies output predicate?

    // destructor:
    inline ~TriangNode();

    // assignments:
    inline TriangNode& operator=(const TriangNode&);
    inline TriangNode& operator=(TriangNode&&);

    // modifiers:
    inline void replace_indexset(const parameter_type, const SimplicialComplex::IndexSet&);
    inline void replace_indexset(const parameter_type, SimplicialComplex::IndexSet&&);
    
    // accessors:
    inline const int            ID()                const { return _ID; }
    inline const parameter_type no()                const { return _no; }
    inline const parameter_type rank()              const { return _rank; }
    inline const bool           valid()             const { return _valid; }

    // modifiers for mutables:
    inline void invalidate() const;

    // functions:
    bool containment_ok(const Circuit& c) const;
    bool link_ok(const Circuit& c) const;

  public:
    // comparison operators:
    inline bool operator==(const TriangNode&) const;

  public:
    // stream output/input:
    inline std::ostream& write(std::ostream& ost) const;
    inline std::istream& read(std::istream& ist);
    friend inline std::ostream& operator<<(std::ostream& ost, const TriangNode& tn);
    friend inline std::istream& operator>>(std::istream& ist, TriangNode& tn);
  };


  // constructors:
  inline TriangNode::TriangNode() : 
    SimplicialComplex(), _ID(-1), _no(0), _rank(0), _valid(true) {}

  inline TriangNode::TriangNode(const int ID,
				const parameter_type no, 
				const parameter_type rank,
				const SimplicialComplex& triang,
				const bool valid) : 
    SimplicialComplex(triang),
    _ID(ID), _no(no), _rank(rank), _valid(valid) {
    assert(_rank = triang.pure_rank());
  }

  inline TriangNode::TriangNode(const int ID,
				const parameter_type no, 
				const parameter_type rank,
				SimplicialComplex&& triang,
				const bool valid) : 
    SimplicialComplex(std::move(triang)),
    _ID(ID), _no(no), _rank(rank), _valid(valid) {
    assert(_rank = triang.pure_rank());
  }

  inline TriangNode::TriangNode(const TriangNode& tn) : 
    SimplicialComplex(tn), 
    _ID(tn._ID), _no(tn._no), _rank(tn._rank), _valid(tn._valid) {}

  inline TriangNode::TriangNode(TriangNode&& tn) : 
    SimplicialComplex(std::move(tn)), 
    _ID(tn._ID), _no(tn._no), _rank(tn._rank), _valid(tn._valid) {}

  inline TriangNode::TriangNode(const int ID,
				const TriangNode& tn) :
    SimplicialComplex(tn), 
    _ID(ID), _no(tn._no), _rank(tn._rank), _valid(tn._valid) {
  }

  inline TriangNode::TriangNode(const int ID,
				const TriangNode& tn,
				const Flip& flip,
				const bool valid) :
    SimplicialComplex(tn), 
    _ID(ID), _no(tn._no), _rank(tn._rank), _valid(valid) {
    
    // flip the flip:
    *this -= flip.first;
    *this += flip.second;
  }

  // destructor:
  inline TriangNode::~TriangNode() {}

  // assignment:
  inline TriangNode& TriangNode::operator=(const TriangNode& tn) {
    if (this == &tn) {
      return *this;
    }
    SimplicialComplex::operator=(tn);
    _ID = tn._ID;
    _no = tn._no;
    _rank = tn._rank;
    _valid = tn._valid;
    return *this;
  }

  inline TriangNode& TriangNode::operator=(TriangNode&& tn) {
    if (this == &tn) {
      return *this;
    }
    SimplicialComplex::operator=(std::move(tn));
    _ID = tn._ID;
    _no = tn._no;
    _rank = tn._rank;
    _valid = tn._valid;
    return *this;
  }

  // comparison operator:
  inline bool TriangNode::operator==(const TriangNode& tn) const {
    return SimplicialComplex::operator==(tn);
  }

  // modifiers:
  inline void TriangNode::invalidate() const {
    _valid = false;
  }

  inline void TriangNode::replace_indexset(const parameter_type rank, const SimplicialComplex::IndexSet& new_is) {

    // the resulting pure rank must be specified, since it may differ from _rank:
    _rank = rank;
    SimplicialComplex::replace_indexset(new_is, _rank);
  }
  inline void TriangNode::replace_indexset(const parameter_type rank, SimplicialComplex::IndexSet&& new_is) {

    // the resulting pure rank must be specified, since it may differ from _rank:
    _rank = rank;
    SimplicialComplex::replace_indexset(std::move(new_is), _rank);
  }

  // stream output/input:
  inline std::ostream& TriangNode::write(std::ostream& ost) const {
    ost << '[' << _ID << "->" << _no << ',' << _rank << ':' << (SimplicialComplex)(*this) << ']';
    return ost;
  }

  inline std::istream& TriangNode::read(std::istream& ist) {
    char c;

    ist >> c >> _ID >> c >> c >> _no >> c >> _rank >> c;
    SimplicialComplex::read(ist);
    ist >> c;
    return ist;
  }

  inline std::ostream& operator<<(std::ostream& ost, const TriangNode& tn) {
    return tn.write(ost);
  }

  inline std::istream& operator>>(std::istream& ist, TriangNode& tn) {
    return tn.read(ist);
  }

}; // namespace topcom

#endif

// eof TriangNode.hh
