#ifndef EmcAlignment_HH
#define EmcAlignment_HH

#include <iostream>
#include <fstream>
#include <string>
#include <iomanip>

#include "UtlPrintHex.hh"
#include "EmcPhysicalPad.hh"


class EmcAlignment {

public:
  EmcAlignment() {
    for(unsigned z(0);z<30;z++) {

      double zz((2*0.14+0.54)*(z/2)+(0.14+0.07)*(z%2));
      if(z>=10) {
	zz=4.5+(4*0.14+0.54)*((z-10)/2)+(2*0.14+0.07)*((z-10)%2);
      }
      if(z>=20) {
	zz=10.5+(6*0.14+0.54)*((z-20)/2)+(3*0.14+0.07)*((z-20)%2);
      }

      for(unsigned y(0);y<18;y++) {
	for(unsigned x(0);x<18;x++) {
	  _x[18*(18*z+y)+x]=x-8.5;
	  _y[18*(18*z+y)+x]=y-8.5;
	  _z[18*(18*z+y)+x]=zz;
	}
      }
    }
  }

  double x(EmcPhysicalPad p) const {
    assert(p.value()<18*18*30);
    return _x[p.value()];
  }

  void x(EmcPhysicalPad p, double v) {
    assert(p.value()<18*18*30);
    _x[p.value()]=v;
  }

  double y(EmcPhysicalPad p) const {
    assert(p.value()<18*18*30);
    return _y[p.value()];
  }

  void y(EmcPhysicalPad p, double v) {
    assert(p.value()<18*18*30);
    _y[p.value()]=v;
  }

  double z(EmcPhysicalPad p) const {
    assert(p.value()<18*18*30);
    return _z[p.value()];
  }

  void z(EmcPhysicalPad p, double v) {
    assert(p.value()<18*18*30);
    _z[p.value()]=v;
  }

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

    for(unsigned z(0);z<30;z++) {
      for(unsigned y(0);y<18;y++) {
	for(unsigned x(0);x<18;x++) {
	  o << s << " X,Y,Z " << std::setw(3) << x << std::setw(3) << y << std::setw(3) << z 
	    << " = "
	    << std::setw(12) << _x[18*(18*z+y)+x]
	    << std::setw(12) << _y[18*(18*z+y)+x]
	    << std::setw(12) << _z[18*(18*z+y)+x] << std::endl;
	}
      }
    }

    return o;
  }

  bool write(std::string fileName) const {
    std::cout << "EmcAlignment::write()  Opening " << fileName << std::endl;
    std::ofstream o(fileName.c_str());
    return write(o);
  }

  bool write(std::ostream &o) const {
    for(unsigned i(0);i<18*18*30;i++) {
      o << std::setw(4) << i << " "
	<< _x[i] << " "
	<< _y[i] << " "
	<< _z[i] << " " << std::endl;
    }
    return true;
  }

  bool read(std::string fileName) {
    std::cout << "EmcAlignment::read()  Opening " << fileName << std::endl;
    std::ifstream i(fileName.c_str(),std::ios::in);
    if(!i) return false;
    return read(i);
  }

  bool read(std::istream &i) {
    unsigned v;
    i >> v;

    while(i) {
      assert(v<18*18*30);
      i >> _x[v] >> _y[v] >> _z[v];
      if(!i) return false;
      i >> v;
    }

    return true;
  }


private:
  // Ignor angular misalignments for now
  double _x[18*18*30];
  double _y[18*18*30];
  double _z[18*18*30];
};

#endif
