/*
 * RefitTrackAction.cpp
 *
 *  Created on: 10/may/2010
 *      Author: M. Bongi, N. Mori
 */

#include "RefitTrackAction.h"

TRandom3* RefitTrackAction::_r3 = new TRandom3(0);
long int RefitTrackAction::_currEvent = -1;
TString RefitTrackAction::_currTrkParamsFile = "";

float RefitTrackAction::_xmBackup[6], RefitTrackAction::_ymBackup[6];
int RefitTrackAction::_layerXBackup[6], RefitTrackAction::_layerYBackup[6];

void RefitTrackAction::OnGood(PamLevel2 *event) {

  // Do something only if at least one track exists
  if (event->GetTrkLevel2()->GetNTracks() == 0)
    return;

  // Reload the TRK alignment parameters only if they have been changed (ie., if another instance of
  // this class used a different set of parameters).
  if (_trkParamsFile != _currTrkParamsFile) {
    TrkParams::Set(_trkParamsFile, 5);
    _currTrkParamsFile = _trkParamsFile;
  }

  if (_sortingMethod)
    event->SetSortingMethod(_sortingMethod);
  TrkTrack *trkTrack = event->GetTrack(0)->GetTrkTrack();
  if (!trkTrack)
    return;

  // Check if good clusters have meaningful energy releases
  for (UInt_t ip = 0; ip < 6; ip++) {
    if (trkTrack->XGood(ip) == 1 && trkTrack->GetDEDX(ip, 0) <= 0.)
      trkTrack->xgood[ip] = 0; // Set it to bad
    if (trkTrack->YGood(ip) == 1 && trkTrack->GetDEDX(ip, 1) <= 0.)
      trkTrack->ygood[ip] = 0; // Set it to bad
  }

  if (_currEvent != event->GetReadEntry()) {
    // Saves the original track data if the current event (recorded in the static member _currEvent) is
    // different from the actually processed event. This way, multiple instances of the class
    // can run in the same analysis, the backup being done only by the first of them.
    _currEvent = event->GetReadEntry();
    // Save the original cluster status and measured positions
    for (int i = 0; i < 6; i++) {
      _layerXBackup[i] = trkTrack->xgood[0];
      _layerYBackup[i] = trkTrack->ygood[0];
      _xmBackup[i] = trkTrack->xm[i];
      _ymBackup[i] = trkTrack->ym[i];
    }
  }
  else {
    // Current event matches the actually analyzed event, this meaning that another instance of the class
    // has already done a refit. In this case, cluster status and positions must be restored before fitting again.
    for (int i = 0; i < 6; i++) {
      trkTrack->xm[i] = _xmBackup[i];
      trkTrack->ym[i] = _ymBackup[i];
      _layerXBackup[i] = trkTrack->xgood[0];
      _layerYBackup[i] = trkTrack->ygood[0];
    }

  }

  // Apply the gaussian spread

  for (Int_t ip = 0; ip < 6; ip++) {
    // gaussian distributed random number Gauss(mean,sigma) (in cm)
    trkTrack->xm[ip] += _r3->Gaus(0., _spreadX);
    trkTrack->ym[ip] += _r3->Gaus(0., _spreadY);
  }

  // Mask the layers
  if (_maskedViews) {
    if ((_maskedViews & T1X) == T1X)
      trkTrack->xgood[0] = 0;
    if ((_maskedViews & T2X) == T2X)
      trkTrack->xgood[1] = 0;
    if ((_maskedViews & T3X) == T3X)
      trkTrack->xgood[2] = 0;
    if ((_maskedViews & T4X) == T4X)
      trkTrack->xgood[3] = 0;
    if ((_maskedViews & T5X) == T5X)
      trkTrack->xgood[4] = 0;
    if ((_maskedViews & T6X) == T6X)
      trkTrack->xgood[5] = 0;

    if ((_maskedViews & T1Y) == T1Y)
      trkTrack->ygood[0] = 0;
    if ((_maskedViews & T2Y) == T2Y)
      trkTrack->ygood[1] = 0;
    if ((_maskedViews & T3Y) == T3Y)
      trkTrack->ygood[2] = 0;
    if ((_maskedViews & T4Y) == T4Y)
      trkTrack->ygood[3] = 0;
    if ((_maskedViews & T5Y) == T5Y)
      trkTrack->ygood[4] = 0;
    if ((_maskedViews & T6Y) == T6Y)
      trkTrack->ygood[5] = 0;
  }

  trkTrack->FitReset();
  int fail = 0;
  trkTrack->Fit(0, fail, 0);

  if (fail) {
    // Set a flag for the badly-refitted tracks: chi2 < 0
    if (trkTrack->chi2 >= 0.)
      trkTrack->chi2 = -1.;
  }
}
