#ifndef AhcVfeControl_HH
#define AhcVfeControl_HH

#include <string>
#include <iostream>

#include "UtlPack.hh"

#include "CrcFeConfigurationData.hh"


class AhcVfeControl {

public:
  AhcVfeControl();
  AhcVfeControl(UtlPack v);
  AhcVfeControl(unsigned v);

  UtlPack data() const;
  void    data(UtlPack v);

  bool srResIn(CrcFeConfigurationData::Connector c) const;
  void srResIn(CrcFeConfigurationData::Connector c, bool e);
  void srResIn(bool e);

  bool srDIn(CrcFeConfigurationData::Connector c) const;
  void srDIn(CrcFeConfigurationData::Connector c, bool e);
  void srDIn(bool e);

  bool selOut(CrcFeConfigurationData::Connector c) const;
  void selOut(CrcFeConfigurationData::Connector c, bool e);
  void selOut(bool e);

  bool srClkIn(CrcFeConfigurationData::Connector c) const;
  void srClkIn(CrcFeConfigurationData::Connector c, bool e);
  void srClkIn(bool e);

  bool swHoldIn(CrcFeConfigurationData::Connector c) const;
  void swHoldIn(CrcFeConfigurationData::Connector c, bool e);
  void swHoldIn(bool e);

  bool swDacIn(CrcFeConfigurationData::Connector c) const;
  void swDacIn(CrcFeConfigurationData::Connector c, bool e);
  void swDacIn(bool e);

  bool ledSel(CrcFeConfigurationData::Connector c) const;
  void ledSel(CrcFeConfigurationData::Connector c, bool e);
  void ledSel(bool e);

  std::ostream& print(std::ostream &o, std::string s="") const;


private:
  UtlPack _data;
};


#ifdef CALICE_DAQ_ICC


AhcVfeControl::AhcVfeControl() : _data(0) {
}

AhcVfeControl::AhcVfeControl(UtlPack v) : _data(v) {
}

AhcVfeControl::AhcVfeControl(unsigned v) : _data(v) {
}

UtlPack AhcVfeControl::data() const {
  return _data;
}

void AhcVfeControl::data(UtlPack v) {
  _data=v;
}

bool AhcVfeControl::srResIn(CrcFeConfigurationData::Connector c) const {
  if(c==CrcFeConfigurationData::boardA) return _data.bit( 6);
  else                                  return _data.bit( 0);
}

void AhcVfeControl::srResIn(CrcFeConfigurationData::Connector c, bool e) {
  if(c==CrcFeConfigurationData::boardA) _data.bit( 6,e);
  else                                  _data.bit( 0,e);
}

void AhcVfeControl::srResIn(bool e) {
  _data.bit( 6,e);
  _data.bit( 0,e);
}

bool AhcVfeControl::srDIn(CrcFeConfigurationData::Connector c) const {
  if(c==CrcFeConfigurationData::boardA) return _data.bit( 7);
  else                                  return _data.bit( 1);
}

void AhcVfeControl::srDIn(CrcFeConfigurationData::Connector c, bool e) {
  if(c==CrcFeConfigurationData::boardA) _data.bit( 7,e);
  else                                  _data.bit( 1,e);
}

void AhcVfeControl::srDIn(bool e) {
  _data.bit( 7,e);
  _data.bit( 1,e);
}

bool AhcVfeControl::selOut(CrcFeConfigurationData::Connector c) const {
  if(c==CrcFeConfigurationData::boardA) return _data.bit( 8);
  else                                  return _data.bit( 2);
}

void AhcVfeControl::selOut(CrcFeConfigurationData::Connector c, bool e) {
  if(c==CrcFeConfigurationData::boardA) _data.bit( 8,e);
  else                                  _data.bit( 2,e);
}

void AhcVfeControl::selOut(bool e) {
  _data.bit( 8,e);
  _data.bit( 2,e);
}

bool AhcVfeControl::srClkIn(CrcFeConfigurationData::Connector c) const {
  if(c==CrcFeConfigurationData::boardA) return _data.bit( 9);
  else                                  return _data.bit( 3);
}

void AhcVfeControl::srClkIn(CrcFeConfigurationData::Connector c, bool e) {
  if(c==CrcFeConfigurationData::boardA) _data.bit( 9,e);
  else                                  _data.bit( 3,e);
}

void AhcVfeControl::srClkIn(bool e) {
  _data.bit( 9,e);
  _data.bit( 3,e);
}

bool AhcVfeControl::swHoldIn(CrcFeConfigurationData::Connector c) const {
  if(c==CrcFeConfigurationData::boardA) return _data.bit(10);
  else                                  return _data.bit( 4);
}

void AhcVfeControl::swHoldIn(CrcFeConfigurationData::Connector c, bool e) {
  if(c==CrcFeConfigurationData::boardA) _data.bit(10,e);
  else                                  _data.bit( 4,e);
}

void AhcVfeControl::swHoldIn(bool e) {
  _data.bit(10,e);
  _data.bit( 4,e);
}

bool AhcVfeControl::swDacIn(CrcFeConfigurationData::Connector c) const {
  if(c==CrcFeConfigurationData::boardA) return _data.bit(11);
  else                                  return _data.bit( 5);
}

void AhcVfeControl::swDacIn(CrcFeConfigurationData::Connector c, bool e) {
  if(c==CrcFeConfigurationData::boardA) _data.bit(11,e);
  else                                  _data.bit( 5,e);
}

void AhcVfeControl::swDacIn(bool e) {
  _data.bit(11,e);
  _data.bit( 5,e);
}

bool AhcVfeControl::ledSel(CrcFeConfigurationData::Connector c) const {
  if(c==CrcFeConfigurationData::boardA) return !_data.bit(15);
  else                                  return !_data.bit(13);
}

void AhcVfeControl::ledSel(CrcFeConfigurationData::Connector c, bool e) {
  if(c==CrcFeConfigurationData::boardA) _data.bit(15,!e);
  else                                  _data.bit(13,!e);
}

void AhcVfeControl::ledSel(bool e) {
  _data.bit(15,!e);
  _data.bit(13,!e);
}

std::ostream& AhcVfeControl::print(std::ostream &o, std::string s) const {
  o << s << "AhcVfeControl::print()" << std::endl;

  o << s << " VFE control = " << printHex(_data) << std::endl;

  for(unsigned i(0);i<2;i++) {
    CrcFeConfigurationData::Connector c((CrcFeConfigurationData::Connector)i);
 
    if(c==CrcFeConfigurationData::bot) o << s << "  Board A settings: enabled";
    else                               o << s << "  Board B settings: enabled";

    bool none(true);
    if(srResIn(c))  {o << ", SR_RES_IN";none=false;}
    if(srDIn(c))    {o << ", SR_D_IN";none=false;}
    if(selOut(c))   {o << ", SEL_OUT";none=false;}
    if(srClkIn(c))  {o << ", SR_CLK_IN";none=false;}
    if(swHoldIn(c)) {o << ", SW_HOLD_IN";none=false;}
    if(swDacIn(c))  {o << ", SW_DAC_IN";none=false;}
    if(ledSel(c))   {o << ", LED_SEL";none=false;}
    if(none) o << ", none";

    o << ";  disabled";
    none=true;
    if(!srResIn(c))  {o << ", SR_RES_IN";none=false;}
    if(!srDIn(c))    {o << ", SR_D_IN";none=false;}
    if(!selOut(c))   {o << ", SEL_OUT";none=false;}
    if(!srClkIn(c))  {o << ", SR_CLK_IN";none=false;}
    if(!swHoldIn(c)) {o << ", SW_HOLD_IN";none=false;}
    if(!swDacIn(c))  {o << ", SW_DAC_IN";none=false;}
    if(!ledSel(c))   {o << ", LED_SEL";none=false;}
    if(none) o << ", none";
    o << std::endl;
  }

  return o;
}

#endif
#endif
