/*****************************
File:     RemoteSunc.h
Language:   C++ (header)
Project:    H3DNetworkingUtils
The contents of this file are subject to the Mozilla Public License
Version 1.1 (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.mozilla.org/MPL/

Software distributed under the License is distributed on an "AS IS"
basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
License for the specific language governing rights and limitations
under the License.

The Original Code is H3DNetworkingUtils v1.0.

The Initial Developer of the Original Code is CSIRO.
Portions created by the Initial Developer are Copyright (C) 1009 CSIRO. All Rights Reserved.
Contributor(s):
    Chris Gunn  <Chris.Gunn@csiro.au> <ChrisJGunn@gmail.com>
***************************/

/// \file RemoteSync.h
/// \brief Header file for RemoteSync, a tuning tool to determine and accomodate for the the latency in a network.

#ifndef RemoteSync_H
#define RemoteSync_H

#include "H3DNetworkingUtils/Config.h"
#include <H3D/Group.h>
#include <H3D/TimeSensor.h>
#include "H3DNetworkingUtils/TimePacket.h"
#include "H3DNetworkingUtils/RemoteTimePacket.h"
#include "H3DNetworkingUtils/PacketSequenceChecker.h"
#include <vector>

namespace H3DNetworkingUtils {
   
/// \class RemoteSync
/// The RemoteSync class is a tuning tool to determine and accomodate for the the latency in a network.

class H3D_NETWORKING_UTILS_DLL_SPEC RemoteSync : public H3D::Group {
public:

   // Forward references
   class ClockOffset;
   struct TimePacketCollector;
   typedef H3D::TypedSFNode<RemoteTimePacket> SFRemoteTimePacket;
  
   /// Constructor
   RemoteSync( H3D::Inst<ClockOffset > _clockOffset = 0,
               H3D::Inst< TimePacketCollector > _timePacketReceived = 0,
               H3D::Inst< SFRemoteTimePacket> _remoteTimePacket = 0);

   /// X3D interface
   static H3D::H3DNodeDatabase database;
    
   /// Initialize
   virtual void initialize();
  
   struct H3D_NETWORKING_UTILS_DLL_SPEC TimePacker : 
                         public H3D::TypedField< H3D::SField< TimePacket >, 
                                                      H3D::SFTime > { 
      virtual void update();
   };
  
  
   struct H3D_NETWORKING_UTILS_DLL_SPEC TimePacketCollector : public H3D::AutoUpdate < 
                                H3D::TypedField<H3D::Field, H3D::SField<TimePacket> > > {
     TimePacketCollector() : remote_syncP (0) {}
     virtual void update() {
        H3D::SField<TimePacket> * packet = static_cast<H3D::SField<TimePacket> *>(event.ptr);
        remote_syncP->appendResult(packet->getValue());
     }
     RemoteSync * remote_syncP;
   };

   class H3D_NETWORKING_UTILS_DLL_SPEC ClockOffset : public H3D::PeriodicUpdate< H3D::SFTime > {
   public:
      ClockOffset(): rs( 0 ) {
         startup = true;
      }
      virtual void update();
      RemoteSync *rs;
   private:
      bool startup;
   };

  
   // Public fields

   /// access type: outputOutput \n
   /// basic type: SFTime \n
   /// default value: 0.0
   auto_ptr< ClockOffset          > clockOffset;
   
   /// access type: inputOnly \n
   /// basic type: Field \n
   /// default value: 
   auto_ptr< TimePacketCollector  > timePacketReceived;
   
   /// access type: initializeOnly \n
   /// basic type: SFNode \n
   /// default value: 
   auto_ptr< SFRemoteTimePacket   > remoteTimePacket;
   
   H3D::AutoRef< H3D::TimeSensor > timer;
   std::vector< TimePacket > results;

protected:
   virtual void appendResult(TimePacket const & packet) {
      if (packet.state)
         results.push_back(packet);
   }
  
   auto_ptr< TimePacker > time_packer;
  
};

}

#endif
