#include "TUnitsTableParser.hxx"
#include <iostream>
#include <sstream>
#include <string>

#include <math.h>

TUnitsTableParser::TUnitsTableParser() {

  // Define units.  Add to this list as needed.

  // Base units
  units["m"] = 100.;
  units["s"] = 1.e+09;
  units["eV"] = 1e-06;
  units["rad"] = 1.;
  units["sr"] = 1 ;

  // Length 
  units["km"] = units["m"]*1.e3;
  units["cm"] = units["m"]*1.e-2;
  units["mm"] = units["m"]*1.e-3;
  units["um"] = units["m"]*1.e-6;
  units["nm"] = units["m"]*1.e-9;
  units["Ang"] = units["m"]*1.e-10;
  units["fm"] = units["m"]*1.e-12;
  units["pc"] = units["m"]*3.08568e+16;

  // Area
  units["km2"] = units["km"]*units["km"];
  units["m2"] = units["m"]*units["m"];
  units["cm2"] = units["cm"]*units["cm"];
  units["mm2"] = units["mm"]*units["mm"];
  units["barn"] = units["m"]*1.e-28 ;
  units["mbarn"] = units["barn"]*1.e-3;
  units["mubarn"] = units["barn"]*1.e-6;
  units["nbarn"] = units["barn"]*1.e-9;
  units["pbarn"] = units["barn"]*1.e-12;

  // Volume
  units["km3"] = units["km"]*units["km"]*units["km"];
  units["m3"] = units["m"]*units["m"]*units["m"];
  units["cm3"] = units["cm"]*units["cm"]*units["cm"];
  units["mm3"] = units["mm"]*units["mm"]*units["mm"];

  // Degree
  units["mrad"] = units["rad"]*1.e-3;
  units["deg"] = units["rad"]*0.0174533 ;

  // Time
  units["ms"] = units["s"]*1.e-3;
  units["mus"] = units["s"]*1.e-6;
  units["ns"] = units["s"]*1.e-9;
  units["ps"] = units["s"]*1.e-12;

  // Frequency
  units["Hz"] = 1./units["s"];
  units["kHz"] = units["Hz"]*1.e3;
  units["MHz"] = units["Hz"]*1.e6;

  // Electric Charge
  units["e+"] = 1  ;
  units["C"] = 6.24151e+18 ;

  // Energy
  units["keV"] = units["eV"]*1.e3;
  units["MeV"] = units["eV"]*1.e6;
  units["GeV"] = units["eV"]*1.e9;
  units["TeV"] = units["eV"]*1.e12;
  units["PeV"] = units["eV"]*1.e15;
  units["J"] = units["eV"]*6.24151e+18;

  // Energy/Length
  units["GeV/cm"] = units["GeV"]/units["cm"];
  units["MeV/cm"] = units["MeV"]/units["cm"];
  units["keV/cm"] = units["keV"]/units["cm"];
  units["eV/cm"] = units["eV"]/units["cm"];

  // Inverse energy  
  units["1/eV"] = 1.0/units["eV"];  ;
  units["1/keV"] = 1.0/units["keV"];  ;
  units["1/MeV"] = 1.0/units["MeV"];  ;
  units["1/GeV"] = 1.0/units["GeV"];  ;

  // Comment out units that I don't understand for now
//  // Mass
//  units["mg"] = 6.24151e+18  ;
//  units["g"] = 6.24151e+21 ;
//  units["kg"] = 6.24151e+24  ;
//
//  // Volumic Mass
//  units["g/cm3"] = 6.24151e+18 ;
//  units["mg/cm3"] = 6.24151e+15  ;
//  units["kg/m3"] = 6.24151e+15 ;
//
//  // Mass/Surface
//  units["g/cm2"] = 6.24151e+19 ;
//  units["mg/cm2"] = 6.24151e+16  ;
//  units["kg/cm2"] = 6.24151e+22  ;
//
//  // Surface/Mass
//  units["cm2/g"] = 1.60218e-20  ;
//
//  // Energy*Surface/Mass
//  units["eV*cm2/g"] = 1.60218e-26 ;
//  units["keV*cm2/g"] = 1.60218e-23  ;
//  units["MeV*cm2/g"] = 1.60218e-20  ;
//  units["GeV*cm2/g"] = 1.60218e-17  ;
//
//  // Power
//  units["W"] = 6241.51  ;
//
//  // Force
//  units["N"] = 6.24151e+09  ;
//
//  // Pressure
//  units["Pa"] = 6241.51 ;
//  units["bar"] = 6.24151e+08  ;
//  units["atm"] = 6.32421e+08  ;
//
//  // Electric current
//  units["A"] = 6.24151e+09 ;
//  units["mA"] = 6.24151e+06 ;
//  units["muA"] = 6241.51  ;
//  units["nA"] = 6.24151 ;
//
//  // Electric potential
//  units["V"] = 1e-06 ;
//  units["kV"] = 0.001  ;
//  units["MV"] = 1  ;
//
//  // Magnetic flux
//  units["Wb"] = 1000  ;
//
//  // Magnetic flux density
//  units["T"] = 0.001 ;
//  units["kG"] = 0.0001  ;
//  units["G"] = 1e-07 ;

  // Speed
  units["cm/us"] = units["cm"]/units["mus"]  ;
  units["cm/ns"] = units["cm"]/units["ns"]  ;
  units["mm/ns"] = units["mm"]/units["ns"]  ;

  // Length/Energy
  units["mm/MeV"] = units["mm"]/units["MeV"];
  units["mm/keV"] = units["mm"]/units["keV"];
  units["cm/MeV"] = units["cm"]/units["MeV"];
  units["cm/keV"] = units["cm"]/units["keV"];

  // Dummy units for diffusion coefficient
  units["cm/sqrt(cm)"] = units["cm"]/sqrt(units["cm"]);
  units["mm/sqrt(cm)"] = units["mm"]/sqrt(units["cm"]);
  units["um/sqrt(cm)"] = units["um"]/sqrt(units["cm"]);

  // Dummy units for electron mobility
  units["cm2/(Vs)"] = units["cm2"]/(units["V"]*units["s"]);
}


TUnitsTableParser::~TUnitsTableParser() {

}


std::string TUnitsTableParser::Convert2DoubleWithUnit(std::string input){

  double value;
  std::string unit;
  
  std::istringstream line(input);
  if(!(line >> value >> unit)){
    std::cerr << "TUnitsTableParser: badly formatted input string. Returning 0."<<std::endl;
    return "0.0";
  }
  
  // Check if requested unit is in map.
  if(units.find(unit) == units.end()){
    std::cerr << "TUnitsTableParser: requested unit '"
	      << unit << "' not found. Returning 0."<<std::endl;
    return "0.0";
  }

  
  value = value * units[unit];

  char s[256];
  sprintf(s,"%f",value);


  return s;

}


void TUnitsTableParser::PrintListOfUnits() {

  std::cout << std::endl;
  std::cout << "***** List of available units *****" << std::endl <<std::endl;  
  for (std::map<std::string, double>::iterator unit = units.begin();
       unit != units.end(); unit++)
    std::cout << (*unit).first <<  std::endl;
  std::cout << std::endl;

}