/*
 * DeviceAccessor.h
 *
 *  Created on: Jun 10, 2016
 *      Author: Martin Hierholzer
 */

#ifndef CHIMERATK_DEVICE_ACCESSOR_H
#define CHIMERATK_DEVICE_ACCESSOR_H

#include <mtca4u/NDRegisterAccessor.h>

#include "Accessor.h"

namespace ChimeraTK {

  /** A DeviceAccessor is used to provide access to register accessors from the DeviceAccess library. It is a temporary
   *  adapter class which harmonises the different interfaces. @todo TODO Once the control system adapter and the
   *  DeviceAccess interfaces have been harmonised, this class is no longer needed! */
  template< typename UserType >
  class DeviceAccessor : public mtca4u::NDRegisterAccessor<UserType> {
    public:

      /**  */
      DeviceAccessor(boost::shared_ptr<mtca4u::NDRegisterAccessor<UserType>> ndRegisterAccessor, VariableDirection direction,
          UpdateMode mode)
      : mtca4u::NDRegisterAccessor<UserType>(ndRegisterAccessor->getName()),
        impl(ndRegisterAccessor),
        _direction(direction),
        _mode(mode)
      {
        mtca4u::NDRegisterAccessor<UserType>::buffer_2D.resize( impl->getNumberOfChannels() );
        for(size_t i=0; i<impl->getNumberOfChannels(); i++) {
          mtca4u::NDRegisterAccessor<UserType>::buffer_2D[i].resize( impl->getNumberOfSamples() );
        }
      }
      
      void doReadTransfer() override {
        impl->read();
      }
      
      bool doReadTransferNonBlocking() override {
        return impl->readNonBlocking();
      }
      
      void postRead() override {
        mtca4u::NDRegisterAccessor<UserType>::buffer_2D[0].swap(impl->accessChannel(0));
      }
      
      void write() override {
        mtca4u::NDRegisterAccessor<UserType>::buffer_2D[0].swap(impl->accessChannel(0));
        impl->write();
        mtca4u::NDRegisterAccessor<UserType>::buffer_2D[0].swap(impl->accessChannel(0));
      }
      
      unsigned int getNInputQueueElements() const override {
        return impl->getNInputQueueElements();
      }
      
      bool isSameRegister(const boost::shared_ptr<const mtca4u::TransferElement>& other) const override {
        return impl->isSameRegister(other);
      }
      
      bool isReadOnly() const override {
        return impl->isReadOnly();
      }
      
      bool isReadable() const override {
        return impl->isReadable();
      }
      
      bool isWriteable() const override {
        return impl->isWriteable();
      }
      
      std::vector<boost::shared_ptr<mtca4u::TransferElement> > getHardwareAccessingElements() override {
        return impl->getHardwareAccessingElements();
      }
      
      void replaceTransferElement(boost::shared_ptr<mtca4u::TransferElement> other) override {
        impl->replaceTransferElement(other);
      }
      
  protected:

      boost::shared_ptr<mtca4u::NDRegisterAccessor<UserType>> impl;
      VariableDirection _direction;
      UpdateMode _mode;
 };


} /* namespace ChimeraTK */

#endif /* CHIMERATK_DEVICE_ACCESSOR_H */