////////////////////////////////////////////////////////////////////////////////
// 
// FlipResult.hh 
//
//    produced: 01/09/25 jr
//
////////////////////////////////////////////////////////////////////////////////
#ifndef FLIPRESULT_HH
#define FLIPRESULT_HH

#include "CommandlineOptions.hh"
#include "ConfData.hh"
#include "RegularityCheck.hh"
#include "Flip.hh"
#include "TriangNode.hh"

namespace topcom {

  // the following class collects everything that one might want to know
  // about a found flip:
  // it depends on the CommandlineOptions and the algorithm,
  // what information is actually generated:
  class FlipResult {
  private:

    // configuration information, owned by some other class:
    const ConfData&          _confdata;
    
    // minimal triangulation information, owned by some other class:
    const int                _ID; // a unique ID
    const int                _fromID; // the ID of the first incident TriangNode
    const int                _toID; // the ID of the second incident TriangNode
    const FlipRep&           _fliprep; // the actual flip

    // derivable information (zero pointers mean information is not yet available):
    const bool*              _is_regularptr; // whether _fliprep is regular in triangulation _fromID
  public:
    
    // constructors:
    inline FlipResult() = delete;
    inline FlipResult(const ConfData&,
		      const int,
		      const int,
		      const int,
		      const FlipRep&);
    inline FlipResult(const FlipResult&);
    inline FlipResult(FlipResult&&);

    // destructor:
    inline ~FlipResult();

    // assignments:
    inline FlipResult& operator=(const FlipResult&) = delete;
    inline FlipResult& operator=(FlipResult&&) = delete;

    // availability:

    // accessors:
    inline const int                ID()                    const;
    inline const int                fromID()                const;
    inline const int                toID()                  const;
    inline const FlipRep&           fliprep()               const;

    // availability:
    inline const bool               has_is_regular()        const;

    // access:
    inline const bool               is_regular()            const;

    // modifiers:
    inline void                     set_is_regular(const bool);
    inline const bool               make_is_regular(const TriangNode&);

    // internal data computation:

    // comparison operators:
    inline bool operator==(const FlipResult&) 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 FlipResult& fr);
    friend inline std::istream& operator>>(std::istream& ist, FlipResult& fr);
  };
   
  // constructors:
  inline FlipResult::FlipResult(const ConfData&          confdata,
				const int                ID,
				const int                fromID,
				const int                toID,
				const FlipRep&           fliprep) :
    _confdata(confdata),
    _ID(ID),
    _fromID(fromID),
    _toID(toID),
    _fliprep(fliprep),
    _is_regularptr(0) {}
  
  inline FlipResult::FlipResult(const FlipResult& fr) :
    _confdata(fr._confdata),
    _ID(fr._ID),
    _fromID(fr._fromID),
    _toID(fr._toID),
    _fliprep(fr._fliprep),
    _is_regularptr(0) {}
  
  inline FlipResult::FlipResult(FlipResult&& fr) :
    _confdata(fr._confdata),
    _ID(fr._ID),
    _fromID(fr._fromID),
    _toID(fr._toID),
    _fliprep(fr._fliprep),
    _is_regularptr(0) {}
  
  // destructor:
  inline FlipResult::~FlipResult() {
    if (_is_regularptr) {
      delete _is_regularptr;
    }
  }

  // availability:
  inline const bool FlipResult::has_is_regular() const {
    return (_is_regularptr);
  }
  
  // access:
  inline const bool FlipResult::is_regular() const {
    if (!_is_regularptr) {
      MessageStreams::forced() << "FlipResult::is_regular(): not available - exiting" << std::endl;
      exit(1);
    }
    return *_is_regularptr;
  }
  
  // modifiers:
  inline void FlipResult::set_is_regular(const bool is_regular) {
    if (_is_regularptr) {
      delete _is_regularptr;
    }
    _is_regularptr = new bool(is_regular);
  }
  
  inline const bool FlipResult::make_is_regular(const TriangNode& tn) {
    if (_is_regularptr) {
      return *_is_regularptr;
    }
    const Flip flip(tn, _fliprep);
    RegularityCheck regchecker(_confdata, tn, flip.first);
    _is_regularptr = new bool(regchecker.is_regular());
    return *_is_regularptr;
  }

  // accessors:
  inline const int FlipResult::ID() const {
    return _ID;
  }
  inline const int FlipResult::fromID() const {
    return _fromID;
  }
  inline const int FlipResult::toID() const {
    return _toID;
  }
  inline const FlipRep& FlipResult::fliprep() const {
    return _fliprep;
  }

  // modifiers:

  // internal data computation:

  // comparison operators:
  inline bool FlipResult::operator==(const FlipResult& fr) const {
    return ((_confdata == fr._confdata)
	    && (_ID == fr._ID)
	    && (_fromID == fr._fromID)
	    && (_toID == fr._toID)
	    && (_fliprep == fr._fliprep));
  }

  // stream output/input:
  inline std::ostream& FlipResult::write(std::ostream& ost) const {
    ost << ContainerChars::list_start_char
	<< "flipID:" << _ID
	<< ContainerChars::delim_char
	<< "fromID:" << _fromID
	<< ContainerChars::delim_char
	<< "toID:" << _toID
	<< ContainerChars::delim_char
	<< "fliprep:" << _fliprep;
    if (has_is_regular()) {
      ost << ContainerChars::delim_char;
      ost << "is_regular:" << is_regular();
    }
    ost << ContainerChars::list_end_char;
    return ost;
  }
  
  inline std::istream& FlipResult::read(std::istream& ist) {
    MessageStreams::forced() << "FlipResult::read(std::istream&): no read functionality implemented - exiting." << std::endl;
    exit(1);
    return ist;
  }
  
  inline std::ostream& operator<<(std::ostream& ost, const FlipResult& fr) {
    return fr.write(ost);
  }
  
  inline std::istream& operator>>(std::istream& ist, FlipResult& fr) {
    return fr.read(ist);
  }

  
}; // namespace topcom

#endif

// eof FlipResult.hh
