#
# Copyright (c) 2009-2022 CERN. All rights nots expressly granted are
# reserved.
#
# This file is part of iLCDirac
# (see ilcdirac.cern.ch, contact: ilcdirac-support@cern.ch).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# In applying this licence, CERN does not waive the privileges and
# immunities granted to it by virtue of its status as an
# Intergovernmental Organization or submit itself to any jurisdiction.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
"""Unit tests for the CalibrationService."""

from __future__ import print_function
from __future__ import absolute_import
import unittest
import pytest
import os
import shutil
import time
from datetime import datetime
from datetime import timedelta
from xml.etree import ElementTree as et
from shutil import copyfile
from DIRAC import S_OK, S_ERROR
from mock import patch
from mock import MagicMock as Mock
from DIRAC.Core.DISET.RequestHandler import RequestHandler
from ILCDIRAC.CalibrationSystem.Service.CalibrationHandler import CalibrationHandler
from ILCDIRAC.CalibrationSystem.Service.CalibrationRun import CalibrationRun
from Tests.Utilities.GeneralUtils import \
    assertEqualsImproved, assertDiracFailsWith, assertDiracSucceeds, \
    assertDiracSucceedsWith_equals
from ILCDIRAC.CalibrationSystem.Service.DetectorSettings import createCalibrationSettings
from ILCDIRAC.CalibrationSystem.Utilities.functions import readParametersFromSteeringFile
from six.moves import filter
from six.moves import range

__RCSID__ = "$Id$"

MODULE_NAME = 'ILCDIRAC.CalibrationSystem.Service.CalibrationHandler'


@pytest.fixture
def readParameterDict():
  """Read parameter list."""
  from ILCDIRAC.CalibrationSystem.Utilities.functions import readParameterDict

  fileDir = os.path.join(os.environ['ILCDIRAC_BASE_FOLDER'], 'src', 'ILCDIRAC',
                         'CalibrationSystem', 'Utilities', 'auxiliaryFiles')
  fileToRead = os.path.join(fileDir, 'parameterListMarlinSteeringFile.txt')
  parDict = readParameterDict(fileToRead)
  for iKey in parDict.keys():
    if 'CalibrECAL' in iKey:
      parDict[iKey] = '1.0 1.0'
    else:
      parDict[iKey] = 1.0
  return parDict


@pytest.fixture
def calibHandler():
  """Create calibration handler."""
  CalibrationHandler.initializeHandler(None)
  RequestHandler._rh__initializeClass(Mock(), Mock(), Mock(), Mock())
  calibHandler = CalibrationHandler({}, Mock())
  calibHandler.initialize()
  print('Init CalibrationHandler. List of active calibrations: %s' % list(CalibrationHandler.activeCalibrations.keys()))
  yield calibHandler

  if os.path.exists('status'):
    try:
      os.remove('status')
    except OSError:
      print("Failed to clean up CalibrationHandler fixture. Cannot delete file 'status'")
      assert False
  # clean up output directory
  for iCalID in list(CalibrationHandler.activeCalibrations.keys()):
    try:
      dirToDelete = 'calib%s' % iCalID
      if os.path.exists(dirToDelete):
        shutil.rmtree(dirToDelete)
        #  pass
    except EnvironmentError as e:
      print("Failed to delete directory: %s" % dirToDelete, str(e))
      assert False
  CalibrationHandler.activeCalibrations = {}
  CalibrationHandler.calibrationCounter = 0


@pytest.fixture
def copiedFccSteeringFile():
  """Copy steering file for testing."""
  calibID = 1
  workdirName = 'calib%s' % calibID
  if not os.path.exists(workdirName):
    os.makedirs(workdirName)
  src = os.path.join(os.environ['ILCDIRAC_BASE_FOLDER'], 'Tests', 'Files', 'fccReconstruction.xml')
  copyfile(src, '%s/fccReconstruction.xml' % workdirName)
  yield workdirName
  try:
    if os.path.exists(workdirName):
      shutil.rmtree(workdirName)
    #  pass
  except EnvironmentError as e:
    print("Failed to delete directory: %s; ErrMsg: %s" % (workdirName, str(e)))
    assert False


def test_returnTypesOfExportFunctionsOfHandler(mocker, calibHandler):
  """Test returns of export_<> functions.

  Test that returns of all export_<> functions of the handler, which doesn't have input arguments, are standard python
  structures.
  """
  mocker.patch.object(calibHandler, '_getUsernameAndGroup', new=Mock(
      return_value={'OK': True, 'Value': {'username': 'correctUserName', 'group': 'correctUserGroup'}}))
  mocker.patch('ILCDIRAC.CalibrationSystem.Service.CalibrationRun.convert_and_execute',
               side_effect=mimic_convert_and_execute)
  mocker.patch('ILCDIRAC.CalibrationSystem.Service.CalibrationRun.saveCalibrationRun', new=Mock(return_value=S_OK()))
  mocker.patch('ILCDIRAC.CalibrationSystem.Service.CalibrationHandler.saveCalibrationRun',
               new=Mock(return_value=S_OK()))

  calibSetting = createCalibrationSettings('CLD')
  calibSetting.settingsDict['numberOfJobs'] = 200

  for i in range(1, 4):
    calibRun = CalibrationRun(i, {'dummy': ['dummy_inputFiles1', 'dummy_inputFiles2']}, calibSetting.settingsDict)
    mocker.patch.object(calibRun, 'ops', new=Mock(return_value=Mock(), name='Class'))
    mocker.patch.object(calibRun, 'endCurrentStep', new=Mock(return_value=S_OK()))
    calibRun.proxyUserName = 'correctUserName'
    calibRun.proxyUserGroup = 'correctUserGroup'
    calibRun.calibrationFinished = False
    CalibrationHandler.activeCalibrations[i] = calibRun

  allInstanceMembers = dir(calibHandler)
  import re
  myPattern = re.compile('export_*')
  exportFunctionMembers = list(filter(myPattern.match, allInstanceMembers))
  calibHandler.export_killCalibration(1, 'killed by user')

  try:
    # Python 3
    from inspect import getfullargspec as sig
  except ImportError:
    # Python 2
    # example of return: ArgSpec(args=['self'], varargs=None, keywords=None, defaults=None)
    from inspect import getargspec as sig

  for iFunc in exportFunctionMembers:
    if iFunc.endswith(('whoami', 'ping')):
      continue
    methodToCall = getattr(calibHandler, iFunc)
    res = sig(methodToCall)
    TestThisFunction = False
    if len(res.args) == 1:
      if res.args[0] == "self":
        TestThisFunction = True
    elif res.defaults is not None:
      if len(res.args) == len(res.defaults) + 1:
        TestThisFunction = True
    if not TestThisFunction:
      continue
    #  print("Test function: %s" % iFunc)
    res = methodToCall()
    assert isinstance(res, dict)
    assert 'OK' in res
    if res['OK']:
      assert 'Value' in res
      assert isinstance(res['Value'], (int, float, str, dict, list, tuple)) or res['Value'] is None
      if isinstance(res['Value'], (list, tuple)):
        print(res['Value'])
        assert isinstance(res['Value'][0], (int, float, str, dict))
    else:
      assert 'Message' in res
      assert not res['Message']


def test_createCalibration(calibHandler):
  """Test createCalibration."""
  cldSettings = createCalibrationSettings('CLD')
  clicSettings = createCalibrationSettings('CLIC')
  inputData = {'zuds': [], 'gamma': [], 'muon': [], 'kaon': []}
  numberOfEventsPerFile = {'zuds': 33, 'gamma': 33, 'muon': 33, 'kaon': 33}

  # wrong input: missing argument in the first input dict
  res = calibHandler.export_createCalibration(inputData, numberOfEventsPerFile, clicSettings.settingsDict)
  assert not res['OK']
  assert "Following settings have None values: ['outputSE']. All settings have to be set up." in res['Message']
  clicSettings.settingsDict['outputSE'] = 'dummy_outputSE'
  res = calibHandler.export_createCalibration(inputData, numberOfEventsPerFile, clicSettings.settingsDict)
  assert not res['OK']
  assert "Following settings have None values: ['outputPath']. All settings have to be set up." in res['Message']
  cldSettings.settingsDict['outputPath'] = 'dummy_outputPath'
  clicSettings.settingsDict['outputPath'] = 'dummy_outputPath'
  cldSettings.settingsDict['outputSE'] = 'dummy_outputSE'

  # wrong input: missing argument in the first input dict
  res = calibHandler.export_createCalibration(
      {'zuds': [], 'gamma': [], 'muon': []}, numberOfEventsPerFile, clicSettings.settingsDict)
  assert not res['OK']
  assert "doesn't contains all required fields." in res['Message']

  # wrong input: unused extra argument in the first input dict
  res = calibHandler.export_createCalibration({'zuds': [], 'gamma': [], 'muon': [], 'kaon': [], 'wonderParticle': []},
                                              numberOfEventsPerFile, clicSettings.settingsDict)
  assert not res['OK']
  assert "doesn't contains all required fields." in res['Message']

  # wrong input: unused extra argument in the third input dict
  wrongSettings = createCalibrationSettings('CLD').settingsDict
  wrongSettings['outputPath'] = 'dummy_outputPath'
  wrongSettings['outputSE'] = 'dummy_outputSE'
  wrongSettings['dummy'] = 'dummy'
  res = calibHandler.export_createCalibration(inputData, numberOfEventsPerFile, wrongSettings)
  assert not res['OK']
  assert "doesn't contains all required fields." in res['Message']

  # wrong input: missing argument in the third input dict
  wrongSettings = createCalibrationSettings('CLD').settingsDict
  wrongSettings['outputPath'] = 'dummy_outputPath'
  wrongSettings['outputSE'] = 'dummy_outputSE'
  wrongSettings.pop('detectorModel', None)
  res = calibHandler.export_createCalibration(inputData, numberOfEventsPerFile, wrongSettings)
  assert not res['OK']
  assert "doesn't contains all required fields." in res['Message']

  # wrong input: swapped input dictionaries
  res = calibHandler.export_createCalibration(cldSettings.settingsDict, inputData, numberOfEventsPerFile)
  assert not res['OK']
  assert "doesn't contains all required fields." in res['Message']

  # wrong input: wrong values in numberOfEventsPerFile
  wrongNumberOfEventsPerFile = {'zuds': 0, 'gamma': 33, 'muon': 33, 'kaon': 33}
  res = calibHandler.export_createCalibration(inputData, wrongNumberOfEventsPerFile, clicSettings.settingsDict)
  assert not res['OK']
  assert "numberOfEventsPerFile" in res['Message']

  # wrong input: wrong values in numberOfEventsPerFile
  wrongNumberOfEventsPerFile = {'zuds': 1, 'gamma': 33.5, 'muon': 33, 'kaon': 33}
  res = calibHandler.export_createCalibration(inputData, wrongNumberOfEventsPerFile, clicSettings.settingsDict)
  assert not res['OK']
  assert "numberOfEventsPerFile" in res['Message']

  # nJobs > nEvents (0 files for kaons)
  inputData = {'zuds': ["dummy.slcio"], 'gamma': ["dummy.slcio"], 'muon': ["dummy.slcio"], 'kaon': []}
  numberOfEventsPerFile = {'zuds': 133, 'gamma': 133, 'muon': 133, 'kaon': 133}
  res = calibHandler.export_createCalibration(inputData, numberOfEventsPerFile, clicSettings.settingsDict)
  assert not res['OK']
  assert 'kaon' in res['Message']

  # nJobs > nEvents (33 events for muons while nJobs = 100)
  inputData = {'zuds': ["dummy.slcio"], 'gamma': ["dummy.slcio"], 'muon': ["dummy.slcio"], 'kaon': ["dummy.slcio"]}
  numberOfEventsPerFile = {'zuds': 133, 'gamma': 133, 'muon': 33, 'kaon': 133}
  res = calibHandler.export_createCalibration(inputData, numberOfEventsPerFile, clicSettings.settingsDict)
  assert not res['OK']
  assert 'muon' in res['Message']


def addPfoAnalysisProcessor(mainSteeringMarlinRecoFile):
  """Add pfoAnalysis processor to the steering file."""
  mainTree = et.ElementTree()
  mainTree.parse(mainSteeringMarlinRecoFile)
  mainRoot = mainTree.getroot()

  # FIXME TODO properly find path to the file
  # this file should only contains PfoAnalysis processor
  import ILCDIRAC.CalibrationSystem.Utilities as utilities
  pfoAnalysisProcessorFile = os.path.join(utilities.__path__[0], 'auxiliaryFiles/pfoAnalysis.xml')
  if not os.path.exists(pfoAnalysisProcessorFile):
    return S_ERROR("cannot find xml file with pfoAnalysis processor")
  tmpTree = et.parse(pfoAnalysisProcessorFile)
  elementToAdd = tmpTree.getroot()

  if 'MyPfoAnalysis' not in (iEl.attrib['name'] for iEl in mainRoot.iter('processor')):
    tmp1 = mainRoot.find('execute')
    c = et.Element("processor name=\"MyPfoAnalysis\"")
    tmp1.append(c)
    mainRoot.append(elementToAdd)
    #  mainTree.write(mainSteeringMarlinRecoFile)
    root = mainTree.getroot()
    root_str = et.tostring(root)
    # TODO FIXME why write to "test_<fileName>" file???
    #  with open('test_' + mainSteeringMarlinRecoFile, "w") as of:
    with open(mainSteeringMarlinRecoFile, "w") as of:
      of.write(root_str.decode())
  return S_OK()


def test_readInitialParameterDict(copiedFccSteeringFile, mocker):
  """Test readInitialParameterDict."""
  calibSetting = createCalibrationSettings('CLD')
  calibSetting.settingsDict['DDPandoraPFANewProcessorName'] = 'MyDDMarlinPandora_10ns'
  calibSetting.settingsDict['DDCaloDigiName'] = 'MyDDCaloDigi_10ns'
  tmpMock = Mock(name='instance')
  tmpMock.getFile.return_value = S_OK()
  mocker.patch('ILCDIRAC.CalibrationSystem.Service.CalibrationRun.DataManager',
               new=Mock(return_value=tmpMock, name='Class'))
  calibID = int(copiedFccSteeringFile.split('calib')[-1])
  newRun = CalibrationRun(calibID, {'dummy': ['dummy_inputFiles1', 'dummy_inputFiles2']}, calibSetting.settingsDict)
  res = newRun.readInitialParameterDict()
  assert res['OK']
  # check if MaxClusterEnergyToApplySoftComp string have been added to the steering file
  tmpKey = (".//processor[@name='%s']/parameter[@name='MaxClusterEnergyToApplySoftComp']"
            % calibSetting.settingsDict['DDPandoraPFANewProcessorName'])
  tmpDict = {tmpKey: None}
  res = readParametersFromSteeringFile('calib' + str(calibID) + '/fccReconstruction.xml', tmpDict)
  assert res['OK']
  assert tmpDict == {tmpKey: '0'}
  # check case when nEcalThickLayers are not zero
  calibSetting.settingsDict['nEcalThinLayers'] = 40
  calibSetting.settingsDict['nEcalThickLayers'] = 34
  calibSetting.settingsDict['ecalResponseCorrectionForThickLayers'] = 2.4
  newRun = CalibrationRun(calibID, {'dummy': ['dummy_inputFiles1', 'dummy_inputFiles2']}, calibSetting.settingsDict)
  res = newRun.readInitialParameterDict()
  assert res['OK']
  tmpKey = ".//processor[@name='%s']/parameter[@name='ECALLayers']" % calibSetting.settingsDict['DDCaloDigiName']
  tmpDict = {tmpKey: None}
  res = readParametersFromSteeringFile('calib' + str(calibID) + '/fccReconstruction.xml', tmpDict)
  assert res['OK']
  assert tmpDict[tmpKey] == '%s %s' % (calibSetting.settingsDict['nEcalThinLayers'],
                                       calibSetting.settingsDict['nEcalThinLayers']
                                       + calibSetting.settingsDict['nEcalThickLayers'] + 1)


def test_initializeHandler(mocker):
  """Test initializeHandler."""
  mocker.patch('%s.glob.glob' % MODULE_NAME, new=Mock(return_value=['calib2', 'calib4', 'calib78']))
  mocker.patch('%s.loadCalibrationRun' % MODULE_NAME, new=Mock())
  mocker.patch.object(CalibrationHandler, 'loadStatus', new=Mock(return_value=0))

  res = CalibrationHandler.initializeHandler(None)
  assert not res['OK']

  mocker.patch.object(CalibrationHandler, 'loadStatus', new=Mock(return_value=78))
  res = CalibrationHandler.initializeHandler(None)
  assert res['OK']


def mimic_convert_and_execute(inList, _=''):
  """Mimic expected output."""
  from ILCDIRAC.CalibrationSystem.Service.CalibrationRun import CalibrationPhase
  if True in ['ECal_Digi_Extract.py' in str(iEl) for iEl in inList] and True in ['Mean' in str(iEl) for iEl in inList]:
    return S_OK((0, '%s\n' % CalibrationPhase.sampleEnergyFromPhase(CalibrationPhase.ECalDigi)))
  elif (True in ['HCal_Digi_Extract.py' in str(iEl) for iEl in inList]
        and True in ['Mean' in str(iEl) for iEl in inList]):
    return S_OK((0, '%s\n' % CalibrationPhase.sampleEnergyFromPhase(CalibrationPhase.HCalDigi)))
  elif True in ['EM_Extract.py' in str(iEl) for iEl in inList] and True in ['Mean' in str(iEl) for iEl in inList]:
    return S_OK((0, '%s\n' % CalibrationPhase.sampleEnergyFromPhase(CalibrationPhase.ElectroMagEnergy)))
  elif True in ['Had_Extract.py' in str(iEl) for iEl in inList] and True in ['FOM' in str(iEl) for iEl in inList]:
    return S_OK((0, '%s\n' % CalibrationPhase.sampleEnergyFromPhase(CalibrationPhase.HadronicEnergy)))
  elif _ != '':
    return 6.66
  else:
    return S_OK((0, '6.66\n'))


def test_endCurrentStepBasicWorkflow(copiedFccSteeringFile, readParameterDict, mocker):
  """Test endCurrentStepBasicWorkflow."""
  opsMock = Mock(name='instance')
  opsMock.getValue.return_value = 'dummy'
  mocker.patch('ILCDIRAC.CalibrationSystem.Service.CalibrationRun.Operations',
               new=Mock(return_value=opsMock, name='Class'))
  #  mocker.patch('ILCDIRAC.CalibrationSystem.Service.CalibrationRun.updateSteeringFile', new=Mock(return_value=S_OK()))
  mocker.patch('ILCDIRAC.CalibrationSystem.Service.CalibrationRun.convert_and_execute',
               side_effect=mimic_convert_and_execute)
  mocker.patch('ILCDIRAC.CalibrationSystem.Service.CalibrationRun.saveCalibrationRun', new=Mock(return_value=S_OK()))

  calibSetting = createCalibrationSettings('CLD')
  calibSetting.settingsDict['DDPandoraPFANewProcessorName'] = 'MyDDMarlinPandora_10ns'
  calibSetting.settingsDict['DDCaloDigiName'] = 'MyDDCaloDigi_10ns'
  tmpMock = Mock(name='instance')
  tmpMock.getFile.return_value = S_OK()
  mocker.patch('ILCDIRAC.CalibrationSystem.Service.CalibrationRun.DataManager',
               new=Mock(return_value=tmpMock, name='Class'))
  steeringFileName = copiedFccSteeringFile
  calibID = int(steeringFileName.split('calib')[-1])
  addPfoAnalysisProcessor('%s/%s' % (steeringFileName, calibSetting.settingsDict['steeringFile']))
  calibSetting.settingsDict['platform'] = "x86_64-slc5-gcc43-opt"
  newRun = CalibrationRun(calibID, {'dummy': ['dummy_inputFiles1', 'dummy_inputFiles2']}, calibSetting.settingsDict)
  res = newRun.readInitialParameterDict()
  assert res['OK']
  newRun.calibrationConstantsDict[".//processor[@type='PfoAnalysis']/parameter[@name='RootFile']"] = 'pfoAnalysis.root'

  mocker.patch.object(CalibrationRun, '_CalibrationRun__mergePandoraLikelihoodXmlFiles',
                      new=Mock(return_value={'OK': True}))
  stageIDSequence = []
  phaseIDSequence = []
  stepIDSequence = []
  calibFinishedSequence = []
  for _ in range(0, 13):
    stepOutcome = 'stage: %s, phase: %s, step: %s,\tcalibFinished: %s' % (
        newRun.currentStage, newRun.currentPhase, newRun.currentStep, newRun.calibrationFinished)
    print(stepOutcome)
    stageIDSequence.append(newRun.currentStage)
    phaseIDSequence.append(newRun.currentPhase)
    stepIDSequence.append(newRun.currentStep)
    calibFinishedSequence.append(newRun.calibrationFinished)
    newRun.endCurrentStep()
  assert stageIDSequence == [1, 1, 1, 1, 1, 2, 3, 3, 3, 3, 3, 3, 3]
  assert phaseIDSequence == [0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 4, 4]
  assert stepIDSequence == [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 11]
  assert calibFinishedSequence == [False, False, False, False,
                                   False, False, False, False, False, False, False, True, True]


def test_export_checkForStepIncrement(calibHandler, mocker):
  """Test export_checkForStepIncrement."""
  calibSetting = createCalibrationSettings('CLIC')
  calibRun = CalibrationRun(27, {'dummy': ['dummy_inputFiles1', 'dummy_inputFiles2']}, calibSetting.settingsDict)
  calibRun.calibrationFinished = True
  calibRun.calibrationEndTime = (datetime.now() - timedelta(minutes=9, seconds=59,
                                                            milliseconds=10)).strftime(calibRun.timeStampPattern)
  CalibrationHandler.activeCalibrations[27] = calibRun
  CalibrationHandler.timeToKeepCalibrationResultsInMinutes = 100

  mocker.patch.object(calibRun, 'copyResults', new=Mock(return_value=S_OK()))
  mocker.patch('%s.saveCalibrationRun' % MODULE_NAME, new=Mock(return_value=S_OK()))
  mocker.patch('%s.shutil' % MODULE_NAME, new=Mock())

  assert len(CalibrationHandler.activeCalibrations) == 1
  res = calibHandler.export_checkForStepIncrement()
  assert res['OK']
  assert len(CalibrationHandler.activeCalibrations) == 1
  CalibrationHandler.timeToKeepCalibrationResultsInMinutes = -10
  res = calibHandler.export_checkForStepIncrement()
  assert res['OK']
  assert len(CalibrationHandler.activeCalibrations) == 0


def test_finalInterimResultReceived(calibHandler, mocker):
  """Test finalInterimResultReceived."""
  calibSetting = createCalibrationSettings('CLIC')
  calibSetting.settingsDict['numberOfJobs'] = 200
  calibRun = CalibrationRun(1, {'dummy': ['dummy_inputFiles1', 'dummy_inputFiles2']}, calibSetting.settingsDict)
  nJobsTmp = int(calibSetting.settingsDict['numberOfJobs']
                 * calibSetting.settingsDict['fractionOfFinishedJobsNeededToStartNextStep'] - 1)
  for i in range(0, nJobsTmp):
    calibRun.stepResults[calibRun.currentStep].addResult(i, 'dummy')
  assert not calibHandler.finalInterimResultReceived(calibRun, calibRun.currentStep)
  calibRun.stepResults[calibRun.currentStep].addResult(nJobsTmp, 'dummy')
  assert calibHandler.finalInterimResultReceived(calibRun, calibRun.currentStep)

#  def test_regroupInputFile(calibHandler, mocker):
  #  inputFileDir = {'muon': ['muon1', 'muon2', 'muon3', 'muon4', 'muon5'],
  #                  'kaon': ['kaon1', 'kaon2', 'kaon3', 'kaon4', 'kaon5'],
  #                  'gamma': ['gamma1', 'gamma2', 'gamma3', 'gamma4', 'gamma5'],
  #                  'zuds': ['zuds1', 'zuds2', 'zuds3', 'zuds4', 'zuds5']}
#
#    numberOfJobs = 4
#    res = calibHandler._CalibrationHandler__regroupInputFile(inputFileDir, numberOfJobs)
#    assert res['OK']
#    groupedDict = res['Value']
#    for iKey in inputFileDir.keys():
#      assert len(groupedDict[0][iKey]) == 2
#      assert len(groupedDict[1][iKey]) == 1
#
#    numberOfJobs = 2
#    res = calibHandler._CalibrationHandler__regroupInputFile(inputFileDir, numberOfJobs)
#    assert res['OK']
#    groupedDict = res['Value']
#    for iKey in inputFileDir.keys():
#      assert len(groupedDict[0][iKey]) == 3
#      assert len(groupedDict[1][iKey]) == 2


def test_export_submitResult(calibHandler, mocker):
  """Test export_submitResult."""
  mocker.patch.object(CalibrationRun, 'submitJobs', new=Mock())
  #  mocker.patch.object(calibHandler, '_CalibrationHandler__regroupInputFile',
  #                      new=Mock(return_value={'OK': True, 'Value': []}))
  mocker.patch('ILCDIRAC.CalibrationSystem.Service.CalibrationHandler.splitFilesAcrossJobs',
               new=Mock(return_value={'OK': True, 'Value': []}))
  mocker.patch.object(calibHandler, '_getUsernameAndGroup', new=Mock(
      return_value={'OK': True, 'Value': {'username': 'oviazlo', 'group': 'ilc_users'}}))

  inputData = {'zuds': ["dummy.slcio"], 'gamma': ["dummy.slcio"], 'muon': ["dummy.slcio"], 'kaon': ["dummy.slcio"]}
  numberOfEventsPerFile = {'zuds': 133, 'gamma': 133, 'muon': 133, 'kaon': 133}

  calibSettings = createCalibrationSettings('CLIC')
  calibSettings.settingsDict['outputPath'] = 'dummy_outputPath'
  calibSettings.settingsDict['outputSE'] = 'dummy_outputSE'
  res = calibHandler.export_createCalibration(inputData, numberOfEventsPerFile, calibSettings.settingsDict)
  if not res['OK']:
    print('Error message:\t%s' % res['Message'])
    assert False

  print('CalibrationHandler.activeCalibrations.keys(): %s' % list(CalibrationHandler.activeCalibrations.keys()))

  import ILCDIRAC.CalibrationSystem.Utilities as utilities
  fileDir = utilities.__path__[0]
  fileToRead = os.path.join(fileDir, 'auxiliaryFiles/pfoAnalysis.xml')
  from ILCDIRAC.CalibrationSystem.Utilities.fileutils import binaryFileToString
  tmpFile = binaryFileToString(fileToRead)

  calibID = 1
  stageID = 2
  phaseID = 0
  stepID = 0
  workerID = 8234

  res = calibHandler.export_submitResult(calibID, stageID, phaseID, stepID, workerID, tmpFile)
  if not res['OK']:
    print(res)
    assert False
  assert res['OK']

  outFile = CalibrationHandler.activeCalibrations[calibID].stepResults[stepID].results[workerID]
  assert os.path.exists(outFile)
  print(outFile)

  import filecmp
  assert filecmp.cmp(fileToRead, outFile)


def test_mergePandoraLikelihoodXmlFiles(calibHandler, mocker):
  """Test mergePandoraLikelihoodXmlFiles."""
  import ILCDIRAC.CalibrationSystem.Utilities as utilities
  fileDir = utilities.__path__[0]

  mocker.patch.object(CalibrationRun, 'submitJobs', new=Mock())
  opsMock = Mock(name='instance')
  opsMock.getValue.return_value = os.path.join(fileDir, 'auxiliaryFiles')
  mocker.patch('ILCDIRAC.CalibrationSystem.Service.CalibrationRun.Operations',
               new=Mock(return_value=opsMock, name='Class'))
  mocker.patch('ILCDIRAC.CalibrationSystem.Service.CalibrationHandler.splitFilesAcrossJobs',
               new=Mock(return_value={'OK': True, 'Value': []}))
  #  mocker.patch.object(calibHandler, '_CalibrationHandler__regroupInputFile',
  #                      new=Mock(return_value={'OK': True, 'Value': []}))
  mocker.patch.object(calibHandler, '_getUsernameAndGroup', new=Mock(
      return_value={'OK': True, 'Value': {'username': 'oviazlo', 'group': 'ilc_users'}}))

  calibSettings = createCalibrationSettings('CLIC')
  calibSettings.settingsDict['outputPath'] = 'dummy_outputPath'
  calibSettings.settingsDict['outputSE'] = 'dummy_outputSE'
  print('calibSettings.settingsDict: %s' % calibSettings.settingsDict)

  inputData = {'zuds': ["dummy.slcio"], 'gamma': ["dummy.slcio"], 'muon': ["dummy.slcio"], 'kaon': ["dummy.slcio"]}
  numberOfEventsPerFile = {'zuds': 133, 'gamma': 133, 'muon': 133, 'kaon': 133}
  res = calibHandler.export_createCalibration(inputData, numberOfEventsPerFile, calibSettings.settingsDict)
  print('calibHandler.export_createCalibration: %s' % res)
  if not res['OK']:
    print(res['Message'])
    assert False

  fileToRead = os.path.join(os.environ['ILCDIRAC_BASE_FOLDER'], 'Tests/Files/PandoraLikelihoodData9EBin.xml')
  if not os.path.exists(fileToRead):
    assert False
  from ILCDIRAC.CalibrationSystem.Utilities.fileutils import binaryFileToString
  tmpFile = binaryFileToString(fileToRead)

  #  calibID = 1
  #  if os.path.exists("status"):
  #    with open(fileName, 'r') as f:
  #      calibID = int(f.readlines()[0])

  calibID = 1
  stageID = 2
  phaseID = 0
  stepID = 0
  workerID = 654

  print('test_mergePandoraLikelihoodXmlFiles: List of active calibrations: %s' %
        list(CalibrationHandler.activeCalibrations.keys()))

  CalibrationHandler.activeCalibrations[calibID].currentStage = stageID
  CalibrationHandler.activeCalibrations[calibID].currentPhase = phaseID
  CalibrationHandler.activeCalibrations[calibID].currentStep = stepID

  res = calibHandler.export_submitResult(calibID, stageID, phaseID, stepID, workerID, tmpFile)
  if not res['OK']:
    print(res)
    assert False

  nFilesToMerge = 3
  for _ in range(0, nFilesToMerge - 1):
    workerID += 1
    res = calibHandler.export_submitResult(calibID, stageID, phaseID, stepID, workerID, tmpFile)
    if not res['OK']:
      print(res)
      assert False

  res = CalibrationHandler.activeCalibrations[calibID]._CalibrationRun__mergePandoraLikelihoodXmlFiles()
  if not res['OK']:
    print(res)
    assert False

  mergedFile = 'calib%s/newPandoraLikelihoodData.xml' % calibID
  assert os.path.exists(mergedFile)

  from ILCDIRAC.CalibrationSystem.Utilities.functions import searchFilesWithPattern
  inFileList = searchFilesWithPattern('calib%s/stage%s' % (calibID, stageID), '*.xml')

  import re
  diffLines = None
  with open(mergedFile) as file1:
    with open(inFileList[0]) as file2:
      diffLines = set(file1).symmetric_difference(file2)
  diffLines = list(diffLines)
  diffLines = [re.split(r'\>|\<', iLine) for iLine in diffLines]

  # since we merge a few copies of the same file, likelihood functions has to be identical in input and output files
  # the only difference has to be in the number of events in NSignalEvents and NBackgroundEvents fields (lines)
  # this is why there should be 2 unique lines in input and output files --> 4 lines in total
  assert len(diffLines) == 4

  # sum numbers from NSignalEvents and NBackgroundEvents nodes for input and output files
  nSignalEvents = []
  nBackgroundEvents = []
  for iList in diffLines:
    if iList[1] == 'NSignalEvents':
      nSignalEvents.append(sum([int(iEl) for iEl in iList[2].split()]))
    elif iList[1] == 'NBackgroundEvents':
      nBackgroundEvents.append(sum([int(iEl) for iEl in iList[2].split()]))
    else:
      pass

  # NSignalEvents_output = nFilesToMerge * NSignalEvents_input
  # NBackgroundEvents_output = nFilesToMerge * NBackgroundEvents_input
  assert ((nSignalEvents[0] == nFilesToMerge * nSignalEvents[1])
          or (nSignalEvents[1] == nFilesToMerge * nSignalEvents[0]))
  assert ((nBackgroundEvents[0] == nFilesToMerge * nBackgroundEvents[1])
          or (nBackgroundEvents[1] == nFilesToMerge * nBackgroundEvents[0]))

  #  print('nSignalEvents: %s' % nSignalEvents)
  #  print('nBackgroundEvents: %s' % nBackgroundEvents)


def test_simple_killCalibration(calibHandler, mocker):
  """Test killCalibration."""
  CalibrationHandler.activeCalibrations[27] = 'dummy27'
  CalibrationHandler.activeCalibrations[31] = 'dummy31'
  CalibrationHandler.activeCalibrations[20] = 'dummy20'

  #  mocker.patch.object(calibHandler, '_checkClientRequest', new=Mock(
  #      return_value={'OK': True, 'Value': {'username': 'correctUserName', 'group': 'correctUserGroup'}}))

  # wrong calibrationID
  res = calibHandler.export_killCalibration(2, 'dummy')
  assert res['OK']
  assert res['Value'] == 'No calibration with ID: %s was found. Active calibrations: %s' % (2, [20, 27, 31])

  # test function which accept list
  # wrong calibrationID
  res = calibHandler.export_killCalibrations([2, 3])
  assert res['OK']
  assert res['Value'] == {2: S_OK('No calibration with ID: %s was found. Active calibrations: %s' % (2, [20, 27, 31])),
                          3: S_OK('No calibration with ID: %s was found. Active calibrations: %s' % (3, [20, 27, 31]))}
  # wrong input type in the list
  res = calibHandler.export_killCalibrations([2, 'blah'])
  assert not res['OK']
  # clean up
  CalibrationHandler.activeCalibrations = {}


def test_killCalibration(calibHandler, copiedFccSteeringFile, mocker):
  """Test killCalibration."""
  from ILCDIRAC.CalibrationSystem.Utilities.functions import saveCalibrationRun
  calibID = int(copiedFccSteeringFile.split('calib')[-1])
  print('calibID: %s' % calibID)

  #  mocker.patch.object(calibHandler, '_checkClientRequest', new=Mock(
  #      return_value={'OK': True, 'Value': {'username': 'correctUserName', 'group': 'correctUserGroup'}}))
  mocker.patch('ILCDIRAC.CalibrationSystem.Service.CalibrationRun.Operations',
               new=Mock(return_value=Mock(), name='Class'))
  mocker.patch.object(calibHandler, '_getUsernameAndGroup', new=Mock(
      return_value={'OK': True, 'Value': {'username': 'correctUserName', 'group': 'correctUserGroup'}}))
  calibSetting = createCalibrationSettings('CLIC')
  calibSetting.settingsDict['outputPath'] = 'dummy_outputPath'
  calibSetting.settingsDict['outputSE'] = 'dummy_outputSE'
  calibRun = CalibrationRun(1, {'dummy': ['dummy_inputFiles1', 'dummy_inputFiles2']}, calibSetting.settingsDict)
  calibRun.proxyUserName = 'wrongUserName'
  calibRun.proxyUserGroup = 'correctUserGroup'
  CalibrationHandler.activeCalibrations[1] = calibRun
  saveCalibrationRun(calibRun)

  # wrong proxyUserName
  res = calibHandler.export_killCalibration(1, 'dummy')
  assert not res['OK']
  assert res['Message'] == 'Permission denied. Calibration with ID 1 has been created by other user.'
  # wrong proxyUserName
  res = calibHandler.export_killCalibrations([1])
  print('\nSASHA: res: %s' % res)
  assert res['OK']
  assert res['Value'][1]['Message'] == 'Permission denied. Calibration with ID 1 has been created by other user.'
  # wrong proxyUserGroup
  calibRun.proxyUserName = 'correctUserName'
  calibRun.proxyUserGroup = 'wrongUserGroup'
  res = calibHandler.export_killCalibration(1, 'dummy')
  assert not res['OK']
  assert res['Message'] == 'Permission denied. Calibration with ID 1 has been created by other user.'
  # everything is correct
  calibRun.proxyUserName = 'correctUserName'
  calibRun.proxyUserGroup = 'correctUserGroup'
  res = calibHandler.export_killCalibration(1, 'dummy')
  assert res['OK']
  assert CalibrationHandler.idsOfCalibsToBeKilled == [1]
  assert calibRun.calibrationFinished
  assert calibRun.resultsSuccessfullyCopied
  assert calibRun.calibrationEndTime is not None

  # clean up
  CalibrationHandler.activeCalibrations = {}


def test_changeDirectoryToCopyTo(calibHandler, mocker):
  """Test changeDirectoryToCopyTo."""
  mocker.patch('ILCDIRAC.CalibrationSystem.Service.CalibrationRun.Operations',
               new=Mock(return_value=Mock(), name='Class'))
  mocker.patch.object(calibHandler, '_getUsernameAndGroup', new=Mock(
      return_value={'OK': True, 'Value': {'username': 'correctUserName', 'group': 'correctUserGroup'}}))
  calibSetting = createCalibrationSettings('CLIC')
  calibSetting.settingsDict['outputPath'] = 'dummy_outputPath'
  calibSetting.settingsDict['outputSE'] = 'dummy_outputSE'
  calibRun = CalibrationRun(33, {'dummy': ['dummy_inputFiles1', 'dummy_inputFiles2']}, calibSetting.settingsDict)
  calibRun.proxyUserName = 'correctUserName'
  calibRun.proxyUserGroup = 'correctUserGroup'
  CalibrationHandler.activeCalibrations[33] = calibRun

  # wrong proxyUserName
  res = calibHandler.export_changeDirectoryToCopyTo(33, 'newPath', 'newSE')
  assert res['OK']
  assert CalibrationHandler.activeCalibrations[33].settings['outputPath'] == 'newPath'
  assert CalibrationHandler.activeCalibrations[33].settings['outputSE'] == 'newSE'
  assert not CalibrationHandler.activeCalibrations[33].resultsSuccessfullyCopied

  CalibrationHandler.activeCalibrations[33].resultsSuccessfullyCopied = True
  res = calibHandler.export_changeDirectoryToCopyTo(33, 'newPath2', 'newSE2')
  assert res['OK']
  assert CalibrationHandler.activeCalibrations[33].settings['outputPath'] == 'newPath2'
  assert CalibrationHandler.activeCalibrations[33].settings['outputSE'] == 'newSE2'
  assert not CalibrationHandler.activeCalibrations[33].resultsSuccessfullyCopied

  # clean up
  CalibrationHandler.activeCalibrations = {}


def test_resubmitjobs(calibHandler, mocker):
  """Test rusibmit jobs."""
  tmpMock0 = Mock(return_value={'OK': True, 'Value': []})
  mocker.patch.object(calibHandler, 'export_killCalibration', new=tmpMock0)
  tmpMock1 = Mock(name='calibRunMock')
  tmpMock2 = Mock(return_value=S_OK())
  tmpMock1.submitJobs = tmpMock2
  tmpMock1.settings.__getitem__ = Mock(return_value=5)
  tmpMock1.nFailedJobs = 1
  tmpMock1.calibrationFinished = False

  #  mocker.spy(tmpMock1, 'submitJobs')
  #  mocker.spy(calibHandler, 'export_killCalibration')

  CalibrationHandler.activeCalibrations[27] = tmpMock1
  failedJobs = ((27, 123), (27, 443), (27, 554))

  calibHandler.export_resubmitJobs(failedJobs)  # nJobs == 5; nFailedJobs == 3+1
  #  assert tmpMock1.submitJobs.call_count == 1
  assert tmpMock2.call_count == 1
  assert calibHandler.export_killCalibration.call_count == 0
  calibHandler.export_resubmitJobs(failedJobs)  # nJobs == 5; nFailedJobs == 3+3+1
  #  assert tmpMock1.submitJobs.call_count == 1
  assert tmpMock2.call_count == 1
  assert calibHandler.export_killCalibration.call_count == 1


# TODO this function has decorator... which one need to mock
#  def test_submitJobs(calibHandler, mocker):
#    calibSetting = createCalibrationSettings('CLIC')
#    calibSetting.settingsDict['numberOfJobs'] = 4
#
  #  inputFileDir = {'muon': ['muon1', 'muon2', 'muon3', 'muon4', 'muon5'],
  #                  'kaon': ['kaon1', 'kaon2', 'kaon3', 'kaon4', 'kaon5'],
  #                  'gamma': ['gamma1', 'gamma2', 'gamma3', 'gamma4', 'gamma5'],
  #                  'zuds': ['zuds1', 'zuds2', 'zuds3', 'zuds4', 'zuds5']}
#    res = calibHandler._CalibrationHandler__regroupInputFile(inputFileDir, calibSetting.settingsDict['numberOfJobs'])
#    groupedDict = res['Value']
#
#    mocker.patch('ILCDIRAC.CalibrationSystem.Service.CalibrationRun.saveCalibrationRun', new=Mock(return_value=S_OK()))
#    mocker.patch('ILCDIRAC.CalibrationSystem.Service.CalibrationRun.DiracILC', new=Mock(return_value=S_OK()))
#    testRun  = CalibrationRun(1, groupedDict, calibSetting.settingsDict)
#
#    userJobMock = Mock(name='instance')
#    userJobMock.submit.return_value = 'dummy'
#    userJobMock.append.return_value = {'OK': True}
#
#    res = testRun.submitJobs([])
#    assert res == []
#    assert False

# pylint: disable=protected-access,too-many-public-methods,,no-member


class CalibrationHandlerTest(unittest.TestCase):
  """Test the implementation of the methods of the CalibrationService classes."""

  @classmethod
  def setUpClass(cls):
    """Set up class."""
    CalibrationHandler.initializeHandler(None)

  def setUp(self):
    """Create a CalibrationHandler instance so we can check some basic functionality."""
    self.transport_mock = Mock()
    RequestHandler._rh__initializeClass(Mock(), Mock(), Mock(), Mock())
    self.calh = CalibrationHandler({}, self.transport_mock)
    self.calh.initialize()
    # TODO mock this call:
    #  self.ops.getValue("/AvailableTarBalls/%s/%s/%s/pandoraAnalysisHeadBin" % (self.platform,
    #                                 'pandora_calibration_scripts', self.appversion), None)

  def tearDown(self):
    """Clean up."""
    if os.path.exists('status'):
      try:
        os.remove('status')
      except OSError:
        print("Failed to clean up CalibrationHandler fixture. Cannot delete file 'status'")
        assert False
    # clean up output directory
    for iCalID in list(CalibrationHandler.activeCalibrations.keys()):
      dirToDelete = 'calib%s' % iCalID
      if os.path.exists(dirToDelete):
        try:
          shutil.rmtree(dirToDelete)
        except EnvironmentError as e:
          print("Failed to delete directory: %s" % dirToDelete, str(e))
          assert False
    CalibrationHandler.activeCalibrations = {}
    CalibrationHandler.calibrationCounter = 0

# FIXME: Change tests to reflect new way of starting calibration creation

  #
  #  def test_submitresult_old_stepid( self ):
  #    with patch.object( CalibrationRun, 'submitJobs', new=Mock()):
  #      for _ in xrange( 0, 50 ): #creates Calibrations with IDs 1-50
  #        self.calh.export_createCalibration( '', '', [], 0, '', '' )
  #    CalibrationHandler.activeCalibrations[ 27 ].currentStep = 13
  #    assertDiracSucceeds( self.calh.export_submitResult( 27, 12, 9841, [ 5, 6, 2, 1, 7 ] ), self )
  #    for i in xrange( 0, 30 ):
  #      assertEqualsImproved( CalibrationHandler.activeCalibrations[ 27 ].stepResults[ i ].getNumberOfResults(),
  #                            0, self )
  #
  #  def test_submitresult_wrong_calibrationID( self ):
  #    with patch.object( CalibrationRun, 'submitJobs', new=Mock()):
  #      for _ in xrange( 0, 50 ): #creates Calibrations with IDs 1-50
  #        self.calh.export_createCalibration( '', '', [], 0, '', '' )
  #    res = self.calh.export_submitResult( 54, 1, 9841, [ 5, 6, 2, 1, 7 ] )
  #    assertDiracFailsWith( res, 'Calibration with id 54 not found', self )
  #    for i in xrange( 0, 50 ):
  #      assertEqualsImproved( CalibrationHandler.activeCalibrations[ 27 ].stepResults[ i ].getNumberOfResults(),
  #                            0, self )

  #  def test_createcalibration( self ):
  #    CalibrationHandler.calibrationCounter = 834 - 1 # newly created Calibration gets ID 834
  #    job_mock = Mock()
  #    with patch.object( CalibrationRun, 'submitJobs', new=job_mock ):
  #      result = self.calh.export_createCalibration( 'steeringfile', 'version', [ 'inputfile1', 'inputfile2' ],
  #                                                   12, '', '' )
  #    assertDiracSucceedsWith_equals( result, ( 834, job_mock() ), self )
  #    testRun = CalibrationHandler.activeCalibrations[ 834 ]
  #    assertEqualsImproved(
  #      ( testRun.steeringFile, testRun.softwareVersion, testRun.inputFiles, testRun.numberOfJobs ),
  #      ( 'steeringfile', 'version', [ 'inputfile1', 'inputfile2' ], 12 ), self )
  #    assertEqualsImproved( CalibrationHandler.calibrationCounter, 834, self ) # next calibration gets ID 835
  #
  #  def test_resubmitjobs( self ):
  #    calIDsWorkIDs = [ ( 138, 1249 ), ( 123, 1357 ), ( 498626, 4368 ) ]
  #    CalibrationHandler.activeCalibrations[ 138 ] = CalibrationRun(1, '', '', [], 0 )
  #    CalibrationHandler.activeCalibrations[ 123 ] = CalibrationRun(2, '', '', [], 0 )
  #    CalibrationHandler.activeCalibrations[ 498626 ] = CalibrationRun(3, '', '', [], 0 )
  #    with patch.object( CalibrationRun, 'resubmitJob', new=Mock()) as resubmit_mock:
  #      assertDiracSucceeds( self.calh.export_resubmitJobs( calIDsWorkIDs ), self )
  #      assertEqualsImproved( resubmit_mock.mock_calls, [ call( 1249, proxyUserGroup = '', proxyUserName = '' ),
  #                                                        call( 1357, proxyUserGroup = '', proxyUserName = '' ),
  #                                                        call( 4368, proxyUserGroup = '', proxyUserName = '' ) ],
  #                            self )
  #
  #  def test_resubmitjobs_fails( self ):
  #    calIDsWorkIDs = [ ( 138, 1249 ), ( 198735, 1357 ), ( 498626, 4368 ) ]
  #    CalibrationHandler.activeCalibrations[ 138 ] = CalibrationRun( '', '', [], 0 )
  #    CalibrationHandler.activeCalibrations[ 123 ] = CalibrationRun( '', '', [], 0 )
  #    CalibrationHandler.activeCalibrations[ 498626 ] = CalibrationRun( '', '', [], 0 )
  #    with patch.object( CalibrationRun, 'resubmitJob', new=Mock() ):
  #      res = self.calh.export_resubmitJobs( calIDsWorkIDs )
  #      assertDiracFails( res, self )
  #      assertInImproved( 'Could not resubmit all jobs', res[ 'Message' ], self )
  #      assertInImproved( '[(198735, 1357)]', res[ 'Message' ], self )
  #      assertEqualsImproved( [ ( 198735, 1357 ) ], res[ 'failed_pairs' ], self )

  def test_getnumberofjobs(self):
    """Test get number of jobs."""
    with patch.object(CalibrationRun, 'submitJobs', new=Mock()):
      with patch('ILCDIRAC.CalibrationSystem.Utilities.functions.splitFilesAcrossJobs',
                 new=Mock(return_value={'OK': True, 'Value': []})):
        with patch.object(self.calh, '_getUsernameAndGroup',
                          new=Mock(return_value={'OK': True, 'Value': {'username': 'oviazlo', 'group': 'ilc_users'}})):
          tmpDict = {782145: 815, 72453: 421, 189455: 100, 954692: 0, 29485: 1040}
          for iCalID in tmpDict.keys():  # creates Calibrations with IDs 1-50
            calibSettings = createCalibrationSettings('CLIC')
            calibSettings.settingsDict['outputPath'] = 'dummy_outputPath'
            calibSettings.settingsDict['outputSE'] = 'dummy_outputSE'
            calibSettings.settingsDict['numberOfJobs'] = tmpDict[iCalID]
            iCalibRun = CalibrationRun(iCalID, {'muon': [], 'kaon': [], 'gamma': [],
                                                'zuds': []}, calibSettings.settingsDict)
            CalibrationHandler.activeCalibrations[iCalID] = iCalibRun
          result = self.calh.export_getNumberOfJobsPerCalibration()
          assertDiracSucceeds(result, self)
          assertEqualsImproved(result['Value'], tmpDict, self)

  #  def test_getnewparams_calculationfinished( self ):
  #    # TODO rewrite this test
  #    calibSetting = createCalibrationSettings('CLIC')
  #    testRun  = CalibrationRun(1, {'dummy': ['dummy_inputFiles1', 'dummy_inputFiles2']}, calibSetting.settingsDict)
  #    testRun.calibrationFinished = True
  #    CalibrationHandler.activeCalibrations[ 2489 ] = testRun
  #    assertDiracSucceedsWith( self.calh.export_getNewParameters( 2489, 193 ),
  #                             'Calibration finished! End job now', self )

  #  def test_getnewparams_nonewparamsyet( self ):
  #    calibSetting = createCalibrationSettings('CLIC')
  #    testRun  = CalibrationRun(1, {'dummy': ['dummy_inputFiles1', 'dummy_inputFiles2']}, calibSetting.settingsDict)
  #    testRun.currentStep = 149
  #    CalibrationHandler.activeCalibrations[ 2489 ] = testRun
  #    assertDiracSucceedsWith_equals(self.calh.export_getNewParameters( 2489, 149 ),
  #                                   None, self)

  def test_getnewparams_newparams(self):
    """Test get new params."""
    calibSetting = createCalibrationSettings('CLIC')
    calibSetting.settingsDict['outputPath'] = 'dummy_outputPath'
    calibSetting.settingsDict['outputSE'] = 'dummy_outputSE'
    testRun = CalibrationRun(1, {'dummy': ['dummy_inputFiles1', 'dummy_inputFiles2']}, calibSetting.settingsDict)
    testRun.currentStep = 36
    testRun.currentParameterSet = {'dummy': 2435}
    testRun.proxyUserName = 'correctUserName'
    testRun.proxyUserGroup = 'correctUserGroup'
    CalibrationHandler.activeCalibrations[2489] = testRun
    with patch.object(CalibrationHandler, '_checkClientRequest', new=Mock(
        return_value=S_OK())):
      res = self.calh.export_getNewParameters(2489, 35)
      print(res)
      assertDiracSucceedsWith_equals(res, testRun.currentParameterSet, self)

  def test_getnewparams_inactive_calibration(self):
    """Test get new params."""
    print (dir(self.calh))
    inputData = {'zuds': ["dummy.slcio"], 'gamma': ["dummy.slcio"], 'muon': ["dummy.slcio"], 'kaon': ["dummy.slcio"]}
    numberOfEventsPerFile = {'zuds': 133, 'gamma': 133, 'muon': 133, 'kaon': 133}
    with patch.object(CalibrationRun, 'submitJobs', new=Mock()):
      with patch('ILCDIRAC.CalibrationSystem.Utilities.functions.splitFilesAcrossJobs',
                 new=Mock(return_value={'OK': True, 'Value': []})):
        with patch.object(self.calh, '_getUsernameAndGroup',
                          new=Mock(return_value={'OK': True, 'Value': {'username': 'oviazlo', 'group': 'ilc_users'}})):
          for _ in range(0, 50):  # creates Calibrations with IDs 1-50
            calibSettings = createCalibrationSettings('CLIC')
            calibSettings.settingsDict['outputPath'] = 'dummy_outputPath'
            calibSettings.settingsDict['outputSE'] = 'dummy_outputSE'
            res = self.calh.export_createCalibration(inputData, numberOfEventsPerFile, calibSettings.settingsDict)
            if not res['OK']:
              print(res['Message'])
              assert False
          res = self.calh.export_getNewParameters(135, 913)
          print('res: %s' % res)
          assertDiracFailsWith(res, 'CalibrationID is not in active calibrations: 135', self)

  #  @patch('DIRAC.ConfigurationSystem.Client.Helpers.Operations.getValue', return_value='dummyReturnString')
  #  def test_endcurrentstep( self, mock_operations ):
  #    from ILCDIRAC.CalibrationSystem.Service.CalibrationHandler import CalibrationResult
  #    with patch.object( CalibrationRun, 'submitJobs', new=Mock()):
  #      self.calh.export_createCalibration('', '', [], 0, '', '' )
  #    self.calh.activeCalibrations[ 1 ].currentStep = 15
  #    result1 = [ 1, 2.3, 5 ]
  #    result2 = [ 0, 0.2, -0.5 ]
  #    result3 = [ -10, -5.4, 2 ]
  #    res = CalibrationResult()
  #    res.addResult( 2384, result1 )
  #    res.addResult( 742, result2 )
  #    res.addResult( 9354, result3 )
  #    self.calh.activeCalibrations[ 1 ].stepResults[ 15 ] = res
  #    self.calh.activeCalibrations[ 1 ].endCurrentStep()
  #    self.assertTrue( self.calh.activeCalibrations[ 1 ].calibrationFinished, 'Expecting calibration to be finished' )
  #
  #  @patch('DIRAC.ConfigurationSystem.Client.Helpers.Operations.getValue', return_value='dummyReturnString')
  #  def test_endcurrentstep_not_finished( self ):
  #    from ILCDIRAC.CalibrationSystem.Service.CalibrationHandler import CalibrationResult
  #    with patch.object( CalibrationRun, 'submitJobs', new=Mock()):
  #      self.calh.export_createCalibration('', '', [], 0, '', '' )
  #    self.calh.activeCalibrations[ 1 ].currentStep = 14
  #    result1 = [ 1, 2.3, 5 ]
  #    result2 = [ 0, 0.2, -0.5 ]
  #    result3 = [ -10, -5.4, 2 ]
  #    res = CalibrationResult()
  #    res.addResult( 2384, result1 )
  #    res.addResult( 742, result2 )
  #    res.addResult( 9354, result3 )
  #    self.calh.activeCalibrations[ 1 ].stepResults[ 14 ] = res
  #    self.calh.activeCalibrations[ 1 ].endCurrentStep()
  #    self.assertFalse( self.calh.activeCalibrations[ 1 ].calibrationFinished,
  #                      'Expecting calibration to be finished' )

  #  def test_addlists_work( self ):
  #    # Simple case
  #    test_list_1 = [1, 148]
  #    test_list_2 = [-3, 0.2]
  #    calibSetting = createCalibrationSettings('CLIC')
  #    calibSetting.settingsDict['outputPath'] = 'dummy_outputPath'
  #    testobj = CalibrationRun(1, {'dummy': ['dummy_inputFiles1', 'dummy_inputFiles2']}, calibSetting.settingsDict)
  #    res = testobj._CalibrationRun__addLists(test_list_1, test_list_2)
  #    assertEqualsImproved([-2, 148.2], res, self)
  #
  #  def test_addlists_work_2(self):
  #    # More complex case
  #    test_list_1 = [9013, -137.25, 90134, 4278, -123, 'abc', ['a', False]]
  #    test_list_2 = [0, 93, -213, 134, 98245, 'aifjg', ['some_entry', {}]]
  #    calibSetting = createCalibrationSettings('CLIC')
  #    calibSetting.settingsDict['outputPath'] = 'dummy_outputPath'
  #    testobj = CalibrationRun(1, {'dummy': ['dummy_inputFiles1', 'dummy_inputFiles2']}, calibSetting.settingsDict)
  #    res = testobj._CalibrationRun__addLists(test_list_1, test_list_2)
  #    assertEqualsImproved([9013, -44.25, 89921, 4412, 98122, 'abcaifjg',
  #                          ['a', False, 'some_entry', {}]], res, self)
  #
  #  def test_addlists_empty(self):
  #    test_list_1 = []
  #    test_list_2 = []
  #    calibSetting = createCalibrationSettings('CLIC')
  #    calibSetting.settingsDict['outputPath'] = 'dummy_outputPath'
  #    testobj = CalibrationRun(1, {'dummy': ['dummy_inputFiles1', 'dummy_inputFiles2']}, calibSetting.settingsDict)
  #    res = testobj._CalibrationRun__addLists(test_list_1, test_list_2)
  #    assertEqualsImproved([], res, self)
  #
  #  def test_addlists_incompatible(self):
  #    test_list_1 = [1, 83, 0.2, -123]
  #    test_list_2 = [1389, False, '']
  #    calibSetting = createCalibrationSettings('CLIC')
  #    calibSetting.settingsDict['outputPath'] = 'dummy_outputPath'
  #    testobj = CalibrationRun(1, {'dummy': ['dummy_inputFiles1', 'dummy_inputFiles2']}, calibSetting.settingsDict)
  #    with pytest.raises(ValueError) as ve:
  #      testobj._CalibrationRun__addLists(test_list_1, test_list_2)
  #    assertInImproved('the two lists do not have the same number of elements', ve.__str__().lower(), self)

  def test_resubmitJob(self):
    """Test resubmit jobs."""
    pass  # FIXME: Finish atest once corresponding method is written
