// ------------------------------------
//
// translateEvtGent.cc
// Author: Lynn Garren
//
// translate an ID number to or from the standard numbering scheme and EvtGen
// use static maps
//
//  The maps are initialized if and only if the public functions are called.
//  Because the maps are static, the initialization happens only once.
//
//  The user NEVER calls EvtGenPDTMapInit()
//  We use a data table (struct SList) so that compile time is not impacted.
//
//  public functions:
//        int translateEvtGentoPDT( const int id )
//        int translatePDTtoEvtGen( const int id )
//        EvtGenPDTMap const & getEvtGenPDTMap()
//        PDTEvtGenMap const & getPDTEvtGenMap()
//
// ------------------------------------

#include <map>
#include <utility>	// make_pair

#include "HepPID/Version.hh"
#include "HepPID/ParticleIDTranslations.hh"
#include "HepPID/ParticleIDMethods.hh"
#include "HepPID/ParticleName.hh"

namespace HepPID {

 typedef  std::map< int, int >  EvtGenPDTMap;
 typedef  std::map< int, int >  PDTEvtGenMap;

namespace {	// EvtGenPDTMapInit is private

 EvtGenPDTMap const & getEvtGenPDTMap();
 PDTEvtGenMap const & getPDTEvtGenMap();

EvtGenPDTMap const & EvtGenPDTMapInit()
{

  static EvtGenPDTMap  m;

  static const struct {
      int hid;	// EvtGen
      int pid;	// PDT
  } SList[] = {
    {        1,        1 },
    {       -1,       -1 },
    {        2,        2 },
    {       -2,       -2 },
    {        3,        3 },
    {       -3,       -3 },
    {        4,        4 },
    {       -4,       -4 },
    {        5,        5 },
    {       -5,       -5 },
    {        6,        6 },
    {       -6,       -6 },
    {        7,        7 },
    {       -7,       -7 },
    {        8,        8 },
    {       -8,       -8 },
    {       21,       21 },
    {       11,       11 },
    {      -11,      -11 },
    {       12,       12 },
    {      -12,      -12 },
    {       13,       13 },
    {      -13,      -13 },
    {       14,       14 },
    {      -14,      -14 },
    {       15,       15 },
    {      -15,      -15 },
    {       16,       16 },
    {      -16,      -16 },
    {       17,       17 },
    {      -17,      -17 },
    {       18,       18 },
    {      -18,      -18 },
    {       22,       22 },
    {    10022,    10022 },
    {    20022,    20022 },
    {       23,       23 },
    {       24,       24 },
    {      -24,      -24 },
    {       25,       25 },
    {      110,      110 },
    {      990,      990 },
    {       32,       32 },
    {       33,       33 },
    {       34,       34 },
    {      -34,      -34 },
    {       35,       35 },
    {       36,       36 },
    {       37,       37 },
    {      -37,      -37 },
    {       41,       41 },
    {      -41,      -41 },
    {       43,       43 },
    {       44,       44 },
    {      -44,      -44 },
    {       81,       81 },
    {       82,       82 },
    {      -82,      -82 },
    {       83,       83 },
    {       84,       84 },
    {      -84,      -84 },
    {       85,       85 },
    {      -85,      -85 },
    {       86,       86 },
    {      -86,      -86 },
    {       87,       87 },
    {      -87,      -87 },
    {       88,       88 },
    {      -88,      -88 },
    {       89,       89 },
    {      -89,      -89 },
    {       90,       90 },
    {      -90,      -90 },
    {       91,       91 },
    {       92,       92 },
    {       93,       93 },
    {       94,       94 },
    {       95,       95 },
    {       96,       96 },
    {       97,       97 },
    {       98,       98 },
    {       99,       99 },
    {      111,      111 },
    {      211,      211 },
    {     -211,     -211 },
    {  9910211,  9910211 },
    { -9910211, -9910211 },
    {   100111,   100111 },
    {   100211,   100211 },
    {  -100211,  -100211 },
    {      221,      221 },
    {   100221,   100221 },
    {      331,      331 },
    {      113,      113 },
    {  9910113,  9910113 },
    {      213,      213 },
    {     -213,     -213 },
    {   100113,   100113 },
    {   100213,   100213 },
    {  -100213,  -100213 },
    {    30113,    30113 },
    {    30213,    30213 },
    {   -30213,   -30213 },
    {      223,      223 },
    {  9910223,  9910223 },
    {   100223,   100223 },
    {      333,      333 },
    {  9910333,  9910333 },
    {  9000111,  9000111 },
    {  9000211,  9000211 },
    { -9000211, -9000211 },
    {  9010221,  9010221 },
    {    10221,    10221 },
    {    10113,    10113 },
    {    10213,    10213 },
    {   -10213,   -10213 },
    {    10223,    10223 },
    {    10333,    10333 },
    {    20113,    20113 },
    {    20213,    20213 },
    {   -20213,   -20213 },
    {    20223,    20223 },
    {    20333,    20333 },
    {      115,      115 },
    {      215,      215 },
    {     -215,     -215 },
    {      225,      225 },
    {  9020221,  9030221 },
    {      335,      335 },
    {      311,      311 },
    {     -311,     -311 },
    {      310,      310 },
    {      130,      130 },
    {      321,      321 },
    {     -321,     -321 },
    {      313,      313 },
    {     -313,     -313 },
    {      323,      323 },
    {     -323,     -323 },
    {    10311,    10311 },
    {   -10311,   -10311 },
    {    10321,    10321 },
    {   -10321,   -10321 },
    {    10313,    10313 },
    {   -10313,   -10313 },
    {    10323,    10323 },
    {   -10323,   -10323 },
    {      315,      315 },
    {     -315,     -315 },
    {      325,      325 },
    {     -325,     -325 },
    {    20313,    20313 },
    {   -20313,   -20313 },
    {    20323,    20323 },
    {   -20323,   -20323 },
    {   100313,   100313 },
    {  -100313,  -100313 },
    {   100323,   100323 },
    {  -100323,  -100323 },
    {    30313,    30313 },
    {   -30313,   -30313 },
    {    30323,    30323 },
    {   -30323,   -30323 },
    {      317,      317 },
    {     -317,     -317 },
    {      327,      327 },
    {     -327,     -327 },
    {      319,      319 },
    {     -319,     -319 },
    {      329,      329 },
    {     -329,     -329 },
    {      411,      411 },
    {     -411,     -411 },
    {      421,      421 },
    {     -421,     -421 },
    {      413,      413 },
    {     -413,     -413 },
    {      423,      423 },
    {     -423,     -423 },
    {    10411,    10411 },
    {   -10411,   -10411 },
    {    10421,    10421 },
    {   -10421,   -10421 },
    {    10413,    10413 },
    {   -10413,   -10413 },
    {    10423,    10423 },
    {   -10423,   -10423 },
    {      415,      415 },
    {     -415,     -415 },
    {      425,      425 },
    {     -425,     -425 },
    {    20413,    20413 },
    {   -20413,   -20413 },
    {    20423,    20423 },
    {   -20423,   -20423 },
    {      431,      431 },
    {     -431,     -431 },
    {      433,      433 },
    {     -433,     -433 },
    {    10431,    10431 },
    {   -10431,   -10431 },
    {    10433,    10433 },
    {   -10433,   -10433 },
    {      435,      435 },
    {     -435,     -435 },
    {    20433,    20433 },
    {   -20433,   -20433 },
    {    30411,   100411 },
    {   -30411,  -100411 },
    {    30421,   100421 },
    {   -30421,  -100421 },
    {    30413,   100413 },
    {   -30413,  -100413 },
    {    30423,   100423 },
    {   -30423,  -100423 },
    {      511,      511 },
    {     -511,     -511 },
    {      521,      521 },
    {     -521,     -521 },
    {      513,      513 },
    {     -513,     -513 },
    {      523,      523 },
    {     -523,     -523 },
    {    10511,    10511 },
    {   -10511,   -10511 },
    {    10521,    10521 },
    {   -10521,   -10521 },
    {    10513,    10513 },
    {   -10513,   -10513 },
    {    10523,    10523 },
    {   -10523,   -10523 },
    {      515,      515 },
    {     -515,     -515 },
    {      525,      525 },
    {     -525,     -525 },
    {    20513,    20513 },
    {   -20513,   -20513 },
    {    20523,    20523 },
    {   -20523,   -20523 },
    {      531,      531 },
    {     -531,     -531 },
    {      533,      533 },
    {     -533,     -533 },
    {    10531,    10531 },
    {   -10531,   -10531 },
    {    10533,    10533 },
    {   -10533,   -10533 },
    {      535,      535 },
    {     -535,     -535 },
    {    20533,    20533 },
    {   -20533,   -20533 },
    {      541,      541 },
    {     -541,     -541 },
    {      543,      543 },
    {     -543,     -543 },
    {    10541,    10541 },
    {   -10541,   -10541 },
    {    10543,    10543 },
    {   -10543,   -10543 },
    {      545,      545 },
    {     -545,     -545 },
    {    20543,    20543 },
    {   -20543,   -20543 },
    {      441,      441 },
    {   100441,   100441 },
    {      443,      443 },
    {  9910443,  9910443 },
    {   100443,   100443 },
    {    30443,    30443 },
    {  9000443,  9000443 },
    {  9010443,  9010443 },
    {  9020443,  9020443 },
    {    10443,    10443 },
    {    10441,    10441 },
    {    20443,    20443 },
    {      445,      445 },
    {      551,      551 },
    {   100551,   100551 },
    {   200551,   200551 },
    {      553,      553 },
    {   100553,   100553 },
    {   200553,   200553 },
    {   300553,   300553 },
    {  9000553,  9000553 },
    {    10553,    10553 },
    {   110553,   110553 },
    {   210553,   210553 },
    {    10551,    10551 },
    {    20553,    20553 },
    {      555,      555 },
    {   110551,   110551 },
    {   120553,   120553 },
    {   100555,   100555 },
    {   210551,   210551 },
    {   220553,   220553 },
    {   200555,   200555 },
    {    10555,    10555 },
    {   110555,   110555 },
    {    30553,    30553 },
    {    20555,    20555 },
    {      557,      557 },
    {   130553,   130553 },
    {   120555,   120555 },
    {   100557,   100557 },
    {  9000221,  9090221 },
    {     1114,     1114 },
    {    -1114,    -1114 },
    {  9912112,  9912112 },
    { -9912112, -9912112 },
    {     2112,     2112 },
    {    -2112,    -2112 },
    {     2114,     2114 },
    {    -2114,    -2114 },
    {  9912212,  9912212 },
    { -9912212, -9912212 },
    {     2212,     2212 },
    {    -2212,    -2212 },
    {     2214,     2214 },
    {    -2214,    -2214 },
    {     2224,     2224 },
    {    -2224,    -2224 },
    {     3112,     3112 },
    {    -3112,    -3112 },
    {     3114,     3114 },
    {    -3114,    -3114 },
    {     3122,     3122 },
    {    -3122,    -3122 },
    {    13122,    13122 },
    {   -13122,   -13122 },
    {     3124,     3124 },
    {    -3124,    -3124 },
    {    23122,    23122 },
    {   -23122,   -23122 },
    {    33122,    33122 },
    {   -33122,   -33122 },
    {    13124,    13124 },
    {   -13124,   -13124 },
    {    43122,    43122 },
    {   -43122,   -43122 },
    {    53122,    53122 },
    {   -53122,   -53122 },
    {     3126,     3126 },
    {    -3126,    -3126 },
    {    13126,    13126 },
    {   -13126,   -13126 },
    {    13212,    13212 },
    {   -13212,   -13212 },
    {    13214,    13214 },
    {   -13214,   -13214 },
    {    23212,    23212 },
    {   -23212,   -23212 },
    {     3216,     3216 },
    {    -3216,    -3216 },
    {     3212,     3212 },
    {    -3212,    -3212 },
    {     3214,     3214 },
    {    -3214,    -3214 },
    {     3222,     3222 },
    {    -3222,    -3222 },
    {     3224,     3224 },
    {    -3224,    -3224 },
    {     3312,     3312 },
    {    -3312,    -3312 },
    {     3314,     3314 },
    {    -3314,    -3314 },
    {     3322,     3322 },
    {    -3322,    -3322 },
    {     3324,     3324 },
    {    -3324,    -3324 },
    {     3334,     3334 },
    {    -3334,    -3334 },
    {    14122,    14122 },
    {   -14122,   -14122 },
    {    14124,    14124 },
    {   -14124,   -14124 },
    {     4112,     4112 },
    {    -4112,    -4112 },
    {     4114,     4114 },
    {    -4114,    -4114 },
    {     4212,     4212 },
    {    -4212,    -4212 },
    {     4214,     4214 },
    {    -4214,    -4214 },
    {     4222,     4222 },
    {    -4222,    -4222 },
    {     4224,     4224 },
    {    -4224,    -4224 },
    {     4312,     4312 },
    {    -4312,    -4312 },
    {     4322,     4322 },
    {    -4322,    -4322 },
    {     4324,     4324 },
    {    -4324,    -4324 },
    {     4122,     4122 },
    {    -4122,    -4122 },
    {     4132,     4132 },
    {    -4132,    -4132 },
    {     4232,     4232 },
    {    -4232,    -4232 },
    {     4314,     4314 },
    {    -4314,    -4314 },
    {     4332,     4332 },
    {    -4332,    -4332 },
    {     4334,     4334 },
    {    -4334,    -4334 },
    {     4412,     4412 },
    {    -4412,    -4412 },
    {     4414,     4414 },
    {    -4414,    -4414 },
    {     4422,     4422 },
    {    -4422,    -4422 },
    {     4424,     4424 },
    {    -4424,    -4424 },
    {     4432,     4432 },
    {    -4432,    -4432 },
    {     4434,     4434 },
    {    -4434,    -4434 },
    {     5112,     5112 },
    {    -5112,    -5112 },
    {     5114,     5114 },
    {    -5114,    -5114 },
    {     5122,     5122 },
    {    -5122,    -5122 },
    {     5132,     5132 },
    {    -5132,    -5132 },
    {     5212,     5212 },
    {    -5212,    -5212 },
    {     5214,     5214 },
    {    -5214,    -5214 },
    {     5222,     5222 },
    {    -5222,    -5222 },
    {     5224,     5224 },
    {    -5224,    -5224 },
    {     5232,     5232 },
    {    -5232,    -5232 },
    {     5312,     5312 },
    {    -5312,    -5312 },
    {     5314,     5314 },
    {    -5314,    -5314 },
    {     5322,     5322 },
    {    -5322,    -5322 },
    {     5324,     5324 },
    {    -5324,    -5324 },
    {     5332,     5332 },
    {    -5332,    -5332 },
    {     5334,     5334 },
    {    -5334,    -5334 },
    {     2101,     2101 },
    {    -2101,    -2101 },
    {     3101,     3101 },
    {    -3101,    -3101 },
    {     3201,     3201 },
    {    -3201,    -3201 },
    {     4101,     4101 },
    {    -4101,    -4101 },
    {     4201,     4201 },
    {    -4201,    -4201 },
    {     4301,     4301 },
    {    -4301,    -4301 },
    {     5101,     5101 },
    {    -5101,    -5101 },
    {     5201,     5201 },
    {    -5201,    -5201 },
    {     5301,     5301 },
    {    -5301,    -5301 },
    {     5401,     5401 },
    {    -5401,    -5401 },
    {     1103,     1103 },
    {    -1103,    -1103 },
    {     2103,     2103 },
    {    -2103,    -2103 },
    {     2203,     2203 },
    {    -2203,    -2203 },
    {     3103,     3103 },
    {    -3103,    -3103 },
    {     3203,     3203 },
    {    -3203,    -3203 },
    {     3303,     3303 },
    {    -3303,    -3303 },
    {     4103,     4103 },
    {    -4103,    -4103 },
    {     4203,     4203 },
    {    -4203,    -4203 },
    {     4303,     4303 },
    {    -4303,    -4303 },
    {     4403,     4403 },
    {    -4403,    -4403 },
    {     5103,     5103 },
    {    -5103,    -5103 },
    {     5203,     5203 },
    {    -5203,    -5203 },
    {     5303,     5303 },
    {    -5303,    -5303 },
    {     5403,     5403 },
    {    -5403,    -5403 },
    {     5503,     5503 },
    {    -5503,    -5503 },
    {    30343,    30343 },
    {   -30343,   -30343 },
    {    30353,    30353 },
    {   -30353,   -30353 },
    {    30373,    30373 },
    {   -30373,   -30373 },
    {    30383,    30383 },
    {   -30383,   -30383 },
    {    30363,    30363 },
    {   -30363,   -30363 },
    {  450000000,  1000010020 },
    { -450000000, -1000010020 },
    {  460000000,  1000010030 },
    { -460000000, -1000010030 },
    {  470000000,  1000020040 },
    { -470000000, -1000020040 },
    {  490000000,  1000020030 },
    { -490000000, -1000020030 },
    {  480000000,         101 }
  };

  int listSize = sizeof(SList)/sizeof(SList[0]);
  for( int k=0; k!=listSize; ++k) {
      m.insert( std::make_pair( SList[k].hid, SList[k].pid) );
  }
  return m;
}  // EvtGenPDTMapInit()

PDTEvtGenMap const & PDTEvtGenMapInit()
{
    static PDTEvtGenMap m;
    static EvtGenPDTMap const & hmap = getEvtGenPDTMap();
    
    for(EvtGenPDTMap::const_iterator cit=hmap.begin(), mend=hmap.end(); cit!=mend; ++cit ) {
	m.insert( std::make_pair( cit->second, cit->first ));
    }
    return m;
}
  
//
// getEvtGenPDTMap is the ONLY function allowed to call EvtGenPDTMapInit
//
EvtGenPDTMap const & getEvtGenPDTMap()
{
  static EvtGenPDTMap const & hmap = EvtGenPDTMapInit();
  return hmap;
}  // getEvtGenPDTMap()

//
// getPDTEvtGenMap is the ONLY function allowed to call EvtGenPDTMapInit
//
PDTEvtGenMap const & getPDTEvtGenMap()
{
  static PDTEvtGenMap const & hmap = PDTEvtGenMapInit();
  return hmap;
}  // getPDTEvtGenMap()

} // unnamed namespace
  
int translateEvtGentoPDT( const int id )
{
    static EvtGenPDTMap const & hmap = getEvtGenPDTMap();

    EvtGenPDTMap::const_iterator const cit = hmap.find( id );
    // found it in the map
    if ( cit != hmap.end() ) { return cit->second; }
    // check to see if someone has defined a valid particle type
    // that isn't in the map
    if( isValid(id) ) { return id; }
    return 0;
}

int translatePDTtoEvtGen( const int id )
{
    static PDTEvtGenMap const & pmap = getPDTEvtGenMap();

    PDTEvtGenMap::const_iterator const cit = pmap.find( id );
    // found it in the map
    if ( cit != pmap.end() ) { return cit->second; }
    // check to see if someone has defined a valid particle type
    // that isn't in the map
    if( isValid(id) ) { return id; }
    return 0;
}

void writeEvtGenTranslationLine( int i, std::ostream & os  )
{
    // only write map entries
    static EvtGenPDTMap const & hmap = getEvtGenPDTMap();

    EvtGenPDTMap::const_iterator const cit = hmap.find( i );
    // found it in the map
    if ( cit != hmap.end() ) { 
        int id = cit->second;
	os << " EvtGen number: " ;
	os.width(10);
	os << i << "  HepPID number: " ;
	os.width(11);
	os << id << "  " << particleName(id) << std::endl;
	// check reverse translation
	int iback =  translatePDTtoEvtGen(id);
	if(iback != i) {
	    os << " WARNING: " << id << " translates back to " 
	       << iback << " not to " << i << std::endl;
	}
    }
    return;
}  // writeEvtGenTranslationLine()

void  writeEvtGenTranslation( std::ostream & os )
{
    writeVersion( os );
    os << "     HepPID Particle List" << std::endl;
    os << std::endl;

    int id, i, j, q1, q2, q3, l, m;
    // special cases
    for( id=1; id<102; ++id) {
        writeEvtGenTranslationLine(  id, os );
        writeEvtGenTranslationLine( -id, os );
    }
    for( i=11; i<1000; ++i) {
        id = i*10;
        writeEvtGenTranslationLine(  id, os );
        writeEvtGenTranslationLine( -id, os );
    }
    // diquark
    for( q2=1; q2<7; ++q2) {
	for( q1=1; q1<7; ++q1) {
            for( j=1; j<4; ++j) {
        	id = 1000*q2+100*q1+j;
        	writeEvtGenTranslationLine(  id, os );
        	writeEvtGenTranslationLine( -id, os );
	    }
	}
    }
    // mesons
    for( q2=1; q2<10; ++q2) {
	for( q1=1; q1<10; ++q1) {
	    for( j=1; j<10; ++j) {
		for( m=0; m<9; ++m) {
		    for( l=0; l<10; ++l) {
			id = 100000*m+10000*l+100*q2+10*q1+j;
        		writeEvtGenTranslationLine(  id, os );
        		writeEvtGenTranslationLine( -id, os );
			id = 9000000+100000*m+10000*l+100*q2+10*q1+j;
        		writeEvtGenTranslationLine(  id, os );
        		writeEvtGenTranslationLine( -id, os );
		    }
		}
	    }
	}
    }
    // baryons
    for( q3=1; q3<10; ++q3) {
	for( q2=1; q2<10; ++q2) {
	    for( q1=1; q1<10; ++q1) {
		for( j=1; j<10; ++j) {
		    for( m=0; m<9; ++m) {
			id = 10000*m+1000*q3+100*q2+10*q1+j;
        		writeEvtGenTranslationLine(  id, os );
        		writeEvtGenTranslationLine( -id, os );
		    }
		}
	    }
	}
    }
    // ions
    for( i=1; i<=9; ++i) {
	id = 400000000+10000000*i;
        writeEvtGenTranslationLine(  id, os );
        writeEvtGenTranslationLine( -id, os );
    }

    return;
}  // writeEvtGenTranslation()

}	// HepPID
