text: #pragma once
  
  #include <fc/string.hpp>
  #include <fc/time.hpp>
  
  namespace muse { namespace chain {
  
  /*
   * This class represents the basic versioning scheme of the Muse blockchain.
   * All versions are a triple consisting of a major version, hardfork version, and release version.
   * It allows easy comparison between versions. A version is a read only object.
   */
  struct version
  {
     version():v_num(0) {}
     version( uint8_t m, uint8_t h, uint16_t r );
     virtual ~version() {}
  
     bool operator == ( const version& o )const { return v_num == o.v_num; }
     bool operator != ( const version& o )const { return v_num != o.v_num; }
     bool operator <  ( const version& o )const { return v_num <  o.v_num; }
     bool operator <= ( const version& o )const { return v_num <= o.v_num; }
     bool operator >  ( const version& o )const { return v_num >  o.v_num; }
     bool operator >= ( const version& o )const { return v_num >= o.v_num; }
  
     operator fc::string()const;
  
     uint32_t v_num;
  };
  
  struct hardfork_version : version
  {
     hardfork_version():version() {}
     hardfork_version( uint8_t m, uint8_t h ):version( m, h, 0 ) {}
     hardfork_version( version v ) { v_num = v.v_num & 0xFFFF0000; }
     ~hardfork_version() {}
  
     void operator =  ( const version& o ) { v_num = o.v_num & 0xFFFF0000; }
     void operator =  ( const hardfork_version& o ) { v_num = o.v_num & 0xFFFF0000; }
  
     bool operator == ( const hardfork_version& o )const { return v_num == o.v_num; }
     bool operator != ( const hardfork_version& o )const { return v_num != o.v_num; }
     bool operator <  ( const hardfork_version& o )const { return v_num <  o.v_num; }
     bool operator <= ( const hardfork_version& o )const { return v_num <= o.v_num; }
     bool operator >  ( const hardfork_version& o )const { return v_num >  o.v_num; }
     bool operator >= ( const hardfork_version& o )const { return v_num >= o.v_num; }
  
     bool operator == ( const version& o )const { return v_num == ( o.v_num & 0xFFFF0000 ); }
     bool operator != ( const version& o )const { return v_num != ( o.v_num & 0xFFFF0000 ); }
     bool operator <  ( const version& o )const { return v_num <  ( o.v_num & 0xFFFF0000 ); }
     bool operator <= ( const version& o )const { return v_num <= ( o.v_num & 0xFFFF0000 ); }
     bool operator >  ( const version& o )const { return v_num >  ( o.v_num & 0xFFFF0000 ); }
     bool operator >= ( const version& o )const { return v_num >= ( o.v_num & 0xFFFF0000 ); }
  };
  
  struct hardfork_version_vote
  {
     hardfork_version_vote() {}
     hardfork_version_vote( hardfork_version v, fc::time_point_sec t ):hf_version( v ),hf_time( t ) {}
  
     hardfork_version   hf_version;
     fc::time_point_sec hf_time;
  };
  
  } } // muse::chain
  
  namespace fc
  {
     void to_variant( const muse::chain::version& v, variant& var, uint32_t max_depth = 1 );
     void from_variant( const variant& var, muse::chain::version& v, uint32_t max_depth = 1 );
  
     void to_variant( const muse::chain::hardfork_version& hv, variant& var, uint32_t max_depth = 1 );
     void from_variant( const variant& var, muse::chain::hardfork_version& hv, uint32_t max_depth = 1 );
  } // fc
  
  #include <fc/reflect/reflect.hpp>
  FC_REFLECT( muse::chain::version, (v_num) )
  FC_REFLECT_DERIVED( muse::chain::hardfork_version, (muse::chain::version), )
  
  FC_REFLECT( muse::chain::hardfork_version_vote, (hf_version)(hf_time) )
  