#ifndef AhcMapping_HH
#define AhcMapping_HH

/* Throughout, layer is specified as 1-40 */

#include <string>
#include <iostream>

#include "UtlPack.hh"


class AhcMapping {

public:
  enum {
    versionNumber=0
  };
 
  AhcMapping();

  unsigned module(unsigned l) const;
  unsigned slot(unsigned l) const;
  unsigned fe(unsigned l) const;
  unsigned cmb(unsigned l) const;
  unsigned canbusAddress(unsigned l) const;
  unsigned pin(unsigned l) const;

  unsigned layer(unsigned s, unsigned f) const;
  unsigned module(unsigned s, unsigned f) const;
  unsigned cmb(unsigned s, unsigned f) const;
  unsigned canbusAddress(unsigned s, unsigned f) const;
  unsigned pin(unsigned s, unsigned f) const;
  
  void data(unsigned l, unsigned m, unsigned s, unsigned f,
	    unsigned c, unsigned a, unsigned p);

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


private:
  UtlPack _module[10];
  UtlPack _slot[10];
  UtlPack _fe[10];
  UtlPack _cmb[10];
  UtlPack _canbusAddress[10];
  UtlPack _pin[10];
};


#ifdef CALICE_DAQ_ICC

#include "UtlPrintHex.hh"

AhcMapping::AhcMapping() {
}

void AhcMapping::data(unsigned l, unsigned m, unsigned s, unsigned f,
		      unsigned c, unsigned a, unsigned p) {
  assert(l>=1 && l<=40);

  _module       [(l-1)/4].byte((l-1)%4,m);
  _slot         [(l-1)/4].byte((l-1)%4,s);
  _fe           [(l-1)/4].byte((l-1)%4,f);
  _cmb          [(l-1)/4].byte((l-1)%4,c);
  _canbusAddress[(l-1)/4].byte((l-1)%4,a);
  _pin          [(l-1)/4].byte((l-1)%4,p);
}

unsigned AhcMapping::module(unsigned l) const {
  assert(l>=1 && l<=40);
  return _module[(l-1)/4].byte((l-1)%4);
}

unsigned AhcMapping::slot(unsigned l) const {
  assert(l>=1 && l<=40);
  return _slot[(l-1)/4].byte((l-1)%4);
}

unsigned AhcMapping::fe(unsigned l) const {
  assert(l>=1 && l<=40);
  return _fe[(l-1)/4].byte((l-1)%4);
}

unsigned AhcMapping::cmb(unsigned l) const {
  assert(l>=1 && l<=40);
  return _cmb[(l-1)/4].byte((l-1)%4);
}

unsigned AhcMapping::canbusAddress(unsigned l) const {
  assert(l>=1 && l<=40);
  return _canbusAddress[(l-1)/4].byte((l-1)%4);
}

unsigned AhcMapping::pin(unsigned l) const {
  assert(l>=1 && l<=40);
  return _pin[(l-1)/4].byte((l-1)%4);
}

unsigned AhcMapping::layer(unsigned s, unsigned f) const {
  assert(s<22 && f<8);

  for(unsigned l(1);l<=40;l++) {
    if(_slot[(l-1)/4].byte((l-1)%4)==s) {
      if(_fe[(l-1)/4].byte((l-1)%4)==f) {
	return l;
      }
    }
  }

  return 0;
}

unsigned AhcMapping::module(unsigned s, unsigned f) const {
  const unsigned l(layer(s,f));
  if(l==0) return 999;
  return module(l);
}

unsigned AhcMapping::cmb(unsigned s, unsigned f) const {
  const unsigned l(layer(s,f));
  if(l==0) return 999;
  return cmb(l);
}

unsigned AhcMapping::canbusAddress(unsigned s, unsigned f) const {
  const unsigned l(layer(s,f));
  if(l==0) return 999;
  return canbusAddress(l);
}

unsigned AhcMapping::pin(unsigned s, unsigned f) const {
  const unsigned l(layer(s,f));
  if(l==0) return 999;
  return pin(l);
}

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

  for(unsigned l(1);l<=40;l++) {
    if(module(l)!=0 || slot(l)!=0 || fe(l)!=0 ||
       cmb(l)!=0 || canbusAddress(l)!=0 || pin(l)!=0) {

      o << s << " Layer " << std::setw(2) << l
	<< ", module = " << std::setw(2) << module(l)
	<< ", slot/FE = " << std::setw(2) << slot(l) << "/" << fe(l)
	<< ", CMB = " << std::setw(2) << cmb(l)
	<< ", CANbus address = " << std::setw(2) << canbusAddress(l)
	<< ", PIN = " << std::setw(2) << pin(l)
	<< std::endl;
    }  
  }
  
  return o;
}

#endif
#endif
