###############################################################################
# (c) Copyright 2019 CERN for the benefit of the LHCb Collaboration           #
#                                                                             #
# This software is distributed under the terms of the GNU General Public      #
# Licence version 3 (GPL Version 3), copied verbatim in the file "LICENSE".   #
#                                                                             #
# 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.                                       #
###############################################################################
"""BookkeepingManager service is the front-end to the Bookkeeping database."""
from functools import partial

from DIRAC import S_OK, S_ERROR
from DIRAC.Core.DISET.RequestHandler import RequestHandler
from DIRAC.Core.Utilities.Decorators import deprecated
from DIRAC.Core.Utilities.ReturnValues import convertToReturnValue, returnValueOrRaise
from DIRAC.ConfigurationSystem.Client.PathFinder import getServiceSection
from DIRAC.ConfigurationSystem.Client.Helpers import cfgPath
from DIRAC.ConfigurationSystem.Client.Config import gConfig


from LHCbDIRAC.BookkeepingSystem.DB.OracleBookkeepingDB import OracleBookkeepingDB
from LHCbDIRAC.BookkeepingSystem.Service.XMLReader.XMLFilesReaderManager import XMLFilesReaderManager
from LHCbDIRAC.BookkeepingSystem.Client import JEncoder
from LHCbDIRAC.BookkeepingSystem.DB.Utilities import checkEnoughBKArguments

# pylint: disable=invalid-name


default = "ALL"


class BookkeepingManagerHandlerMixin:
    """Bookkeeping Service class.

    It serves the requests made the users by using the BookkeepingClient.
    """

    @classmethod
    def initializeHandler(cls, _serviceInfoDict):
        """Initializes the variables used to identify queries, which are not
        containing enough conditions."""

        cls.bkkDB = OracleBookkeepingDB()
        cls.xmlReader = XMLFilesReaderManager()
        cls.__eventTypeCache = {}

        bkkSection = getServiceSection("Bookkeeping", "BookkeepingManager")
        if not bkkSection:
            cls.email = "lhcb-bookkeeping@cern.ch"
            cls.forceExecution = False
        else:
            cls.email = gConfig.getValue(cfgPath(bkkSection, "Email"), "lhcb-bookkeeping@cern.ch")
            cls.forceExecution = gConfig.getValue(cfgPath(bkkSection, "ForceExecution"), False)
        cls.log.info(f"Email used to track queries: {cls.email} forceExecution", cls.forceExecution)
        return S_OK()

    #############################################################################
    types_sendXMLBookkeepingReport = [str]

    def export_sendXMLBookkeepingReport(self, xml):
        """This method is used to upload an xml report which is produced after when
        the job successfully finished. The input parameter 'xml' is a string which
        contains various information (metadata) about the finished job in the Grid
        in an XML format.

        :param str xml: bookkeeping report
        """
        retVal = self.xmlReader.readXMLfromString(xml)
        if not retVal["OK"]:
            self.log.error("Issue reading XML", retVal["Message"])
        return retVal

    #############################################################################
    types_getAvailableSteps = [dict]

    @classmethod
    def export_getAvailableSteps(cls, in_dict):
        """It returns all the available steps which corresponds to a given
        conditions.

        The in_dict contains the following conditions: StartDate, StepId,
        InputFileTypes, OutputFileTypes,     ApplicationName,
        ApplicationVersion, OptionFiles, DDDB, CONDDB, ExtraPackages,
        Visible, ProcessingPass, Usable, RuntimeProjects, DQTag,
        OptionsFormat, StartItem, MaxItem
        """
        return cls.bkkDB.getAvailableSteps(in_dict)

    #############################################################################
    types_getDataTakingConditionID = [str]

    @classmethod
    def export_getDataTakingConditionID(cls, daq_desc):
        """It returns all the condition ID given the description"""
        return cls.bkkDB._getDataTakingConditionId(daq_desc)

    #############################################################################
    types_getRuntimeProjects = [dict]

    @classmethod
    def export_getRuntimeProjects(cls, in_dict):
        """It returns a runtime project for a given step.

        The input parameter is a in_dictionary which has only one key StepId
        """
        return cls.bkkDB.getRuntimeProjects(in_dict)

    #############################################################################
    types_getStepInputFiles = [int]

    @classmethod
    def export_getStepInputFiles(cls, stepId):
        """It returns the input files for a given step."""
        retVal = cls.bkkDB.getStepInputFiles(stepId)
        if not retVal["OK"]:
            return retVal

        records = [list(record) for record in retVal["Value"]]
        return S_OK({"ParameterNames": ["FileType", "Visible"], "Records": records, "TotalRecords": len(records)})

    #############################################################################
    types_setStepInputFiles = [int, list]

    @classmethod
    def export_setStepInputFiles(cls, stepid, files):
        """It is used to set input file types to a Step."""
        return cls.bkkDB.setStepInputFiles(stepid, files)

    #############################################################################
    types_setStepOutputFiles = [int, list]

    @classmethod
    def export_setStepOutputFiles(cls, stepid, files):
        """It is used to set output file types to a Step."""
        return cls.bkkDB.setStepOutputFiles(stepid, files)

    #############################################################################
    types_getStepOutputFiles = [int]

    @classmethod
    def export_getStepOutputFiles(cls, stepId):
        """It returns the output file types for a given Step."""
        retVal = cls.bkkDB.getStepOutputFiles(stepId)
        if not retVal["OK"]:
            return retVal

        records = []
        parameters = ["FileType", "Visible"]
        for record in retVal["Value"]:
            records += [list(record)]
        return S_OK({"ParameterNames": parameters, "Records": records, "TotalRecords": len(records)})

    #############################################################################
    types_getAvailableFileTypes = []

    @classmethod
    def export_getAvailableFileTypes(cls):
        """more info in the BookkeepingClient.py."""
        return cls.bkkDB.getAvailableFileTypes()

    #############################################################################
    types_insertFileTypes = [str, str, str]

    @classmethod
    def export_insertFileTypes(cls, ftype, desc, fileType):
        """It is used to register a file type. It has the following input
        parameters:

        :param str ftype: file type; for example: COOL.DST
        :param str desc: a short description which describes the file content
        :paran str fileType: the file format such as ROOT, POOL_ROOT, etc.
        """
        return cls.bkkDB.insertFileTypes(ftype, desc, fileType)

    #############################################################################
    types_insertStep = [dict]

    @classmethod
    def export_insertStep(cls, in_dict):
        """It used to insert a step to the Bookkeeping Metadata Catalogue. The
        imput parameter is a dictionary which contains the steps attributes. For
        example: Dictionary format:

        {'Step': {'ApplicationName': 'DaVinci',
        'Usable': 'Yes',
        'StepId': '',
        'ApplicationVersion': 'v29r1', 'ext-comp-1273':
        'CHARM.MDST (Charm micro dst)', 'ExtraPackages': '', 'StepName': 'davinci prb2',
        'ProcessingPass': 'WG-Coool', 'ext-comp-1264': 'CHARM.DST (Charm stream)', 'Visible': 'Y', 'DDDB': '',
        'OptionFiles': '', 'CONDDB': ''}, 'OutputFileTypes': [{'Visible': 'Y', 'FileType': 'CHARM.MDST'}],
        'InputFileTypes': [{'Visible': 'Y', 'FileType': 'CHARM.DST'}],'RuntimeProjects':[{StepId:13878}]}
        """
        return cls.bkkDB.insertStep(in_dict)

    #############################################################################
    types_deleteStep = [int]

    @classmethod
    def export_deleteStep(cls, stepid):
        """It used to delete a given step."""
        return cls.bkkDB.deleteStep(stepid)

    #############################################################################
    types_deleteStepContainer = [int]

    @classmethod
    def export_deleteStepContainer(cls, stepid):
        """It used to delete a given step."""
        return cls.bkkDB.deleteStepContainer(stepid)

    #############################################################################
    types_updateStep = [dict]

    @classmethod
    def export_updateStep(cls, in_dict):
        """It is used to modify the step attributes."""
        return cls.bkkDB.updateStep(in_dict)

    ##############################################################################
    types_getAvailableConfigNames = []

    @classmethod
    def export_getAvailableConfigNames(cls):
        """It returns all the available configuration names which are used."""
        retVal = cls.bkkDB.getAvailableConfigNames()
        if not retVal["OK"]:
            return retVal

        records = [list(record) for record in retVal["Value"]]
        return S_OK({"ParameterNames": ["Configuration Name"], "Records": records, "TotalRecords": len(records)})

    #############################################################################
    types_getConfigVersions = [dict]

    @classmethod
    def export_getConfigVersions(cls, in_dict):
        """It returns all the available configuration version for a given
        condition.

        Input parameter is a dictionary which has the following key: 'ConfigName'
        For example: in_dict = {'ConfigName':'MC'}
        """
        configName = in_dict.get("ConfigName", default)
        retVal = cls.bkkDB.getConfigVersions(configName)
        if not retVal["OK"]:
            return retVal
        records = []
        parameters = ["Configuration Version"]
        for record in retVal["Value"]:
            records += [list(record)]
        return S_OK({"ParameterNames": parameters, "Records": records, "TotalRecords": len(records)})

    #############################################################################
    types_getConditions = [dict]

    @classmethod
    def export_getConditions(cls, in_dict):
        """It returns all the available conditions for a given conditions.

        Input parameter is a dictionary which has the following keys: 'ConfigName', 'ConfigVersion', 'EventType'
        For example: in_dict = {'ConfigName':'MC','ConfigVersion':'MC10'}
        """
        result = S_ERROR()
        ok = True
        configName = in_dict.get("ConfigName", default)
        configVersion = in_dict.get("ConfigVersion", default)
        evt = in_dict.get("EventType", in_dict.get("EventTypeId", default))

        if "EventTypeId" in in_dict:
            cls.log.verbose("EventTypeId will be not accepted! Please change it to EventType")

        retVal = cls.bkkDB.getConditions(configName, configVersion, evt)
        if retVal["OK"]:
            values = retVal["Value"]
            sim_parameters = [
                "SimId",
                "Description",
                "BeamCondition",
                "BeamEnergy",
                "Generator",
                "MagneticField",
                "DetectorCondition",
                "Luminosity",
                "G4settings",
            ]
            daq_parameters = [
                "DaqperiodId",
                "Description",
                "BeamCondition",
                "BeanEnergy",
                "MagneticField",
                "VELO",
                "IT",
                "TT",
                "OT",
                "RICH1",
                "RICH2",
                "SPD_PRS",
                "ECAL",
                "HCAL",
                "MUON",
                "L0",
                "HLT",
                "VeloPosition",
            ]
            sim_records = []
            daq_records = []

            if len(values) > 0:
                for record in values:
                    if record[0] is not None:
                        sim_records += [
                            [
                                record[0],
                                record[2],
                                record[3],
                                record[4],
                                record[5],
                                record[6],
                                record[7],
                                record[8],
                                record[9],
                            ]
                        ]
                    elif record[1] is not None:
                        daq_records += [
                            [
                                record[1],
                                record[10],
                                record[11],
                                record[12],
                                record[13],
                                record[14],
                                record[15],
                                record[16],
                                record[17],
                                record[18],
                                record[19],
                                record[20],
                                record[21],
                                record[22],
                                record[23],
                                record[24],
                                record[25],
                                record[26],
                            ]
                        ]
                    else:
                        result = S_ERROR("Condition does not exist")
                        ok = False
            if ok:
                result = S_OK(
                    [
                        {"ParameterNames": sim_parameters, "Records": sim_records, "TotalRecords": len(sim_records)},
                        {"ParameterNames": daq_parameters, "Records": daq_records, "TotalRecords": len(daq_records)},
                    ]
                )
        else:
            result = retVal

        return result

    #############################################################################
    types_getProcessingPass = [dict, str]

    @classmethod
    def export_getProcessingPass(cls, in_dict, path=None):
        """It returns the processing pass for a given conditions.

        Input parameter is a dictionary and a path (string) which has the following keys:
        'ConfigName', 'ConfigVersion', 'ConditionDescription','Production', 'RunNumber', 'EventType'
        This method is used to recursively browse the processing pass.
        To start the browsing you have to define the path as a root: path = '/'
        Note: it returns a list with two dictionary. First dictionary contains the processing passes
        while the second dictionary contains the event types.
        """
        if path is None:
            path = "/"
        configName = in_dict.get("ConfigName", default)
        configVersion = in_dict.get("ConfigVersion", default)
        conddescription = in_dict.get(
            "ConditionDescription",  # old single
            in_dict.get("SimulationConditions", in_dict.get("DataTakingConditions", default)),
        )
        prod = in_dict.get("Production", default)
        runnb = in_dict.get("RunNumber", default)
        evt = in_dict.get("EventType", in_dict.get("EventTypeId", default))
        return cls.bkkDB.getProcessingPass(configName, configVersion, conddescription, runnb, prod, evt, path)

    #############################################################################
    types_getProductions = [dict]

    @classmethod
    def export_getProductions(cls, in_dict):
        """It returns the productions for a given conditions.

        Input parameter is a dictionary which has the following keys:
        'ConfigName', 'ConfigVersion', 'ConditionDescription',
        'EventType','ProcessingPass'
        """
        configName = in_dict.get("ConfigName", default)
        configVersion = in_dict.get("ConfigVersion", default)
        conddescription = in_dict.get(
            "ConditionDescription",  # old single
            in_dict.get("SimulationConditions", in_dict.get("DataTakingConditions", default)),
        )

        processing = in_dict.get("ProcessingPass", default)
        evt = in_dict.get("EventType", in_dict.get("EventTypeId", default))
        replicaFlag = in_dict.get("ReplicaFlag", "Yes")
        ftype = in_dict.get("FileType", default)
        visible = in_dict.get("Visible", "Y")
        if "EventTypeId" in in_dict:
            cls.log.verbose("The EventTypeId has to be replaced by EventType!")

        retVal = cls.bkkDB.getProductions(
            configName, configVersion, conddescription, processing, evt, visible, ftype, replicaFlag
        )
        if not retVal["OK"]:
            return retVal
        records = []
        parameters = ["Production/RunNumber"]
        for record in retVal["Value"]:
            records += [[record[0]]]
        return S_OK({"ParameterNames": parameters, "Records": records, "TotalRecords": len(records)})

    #############################################################################
    types_getFileTypes = [dict]

    @classmethod
    def export_getFileTypes(cls, in_dict):
        """It returns the file types for a given conditions.

        Input parameter is a dictionary which has the following keys:
        'ConfigName', 'ConfigVersion', 'ConditionDescription', 'EventType','ProcessingPass','Production','RunNumber'
        """
        configName = in_dict.get("ConfigName", default)
        configVersion = in_dict.get("ConfigVersion", default)
        conddescription = in_dict.get(
            "ConditionDescription",  # old single
            in_dict.get("SimulationConditions", in_dict.get("DataTakingConditions", default)),
        )
        processing = in_dict.get("ProcessingPass", default)
        evt = in_dict.get("EventType", in_dict.get("EventTypeId", default))
        production = in_dict.get("Production", default)
        runnb = in_dict.get("RunNumber", default)
        visible = in_dict.get("Visible", "Y")
        replicaflag = in_dict.get("ReplicaFlag", "Yes")

        if "EventTypeId" in in_dict:
            cls.log.verbose("The EventTypeId has to be replaced by EventType!")

        retVal = cls.bkkDB.getFileTypes(
            configName, configVersion, conddescription, processing, evt, runnb, production, visible, replicaflag
        )
        if not retVal["OK"]:
            return retVal
        records = []
        parameters = ["FileTypes"]
        for record in retVal["Value"]:
            records += [[record[0]]]
        return S_OK({"ParameterNames": parameters, "Records": records, "TotalRecords": len(records)})

    #############################################################################
    def transfer_toClient(self, parameters, token, fileHelper):
        """This method is used to transfer data using a file.

        Currently two client methods are using this function: getFiles, getFilesWithMetadata
        """
        in_dict = JEncoder.loads(parameters)
        self.log.verbose("Received the following dictionary:", str(in_dict))
        methodName = in_dict.get("MethodName", default)
        if methodName == "getFiles":
            retVal = self._getFiles(in_dict)
        else:
            retVal = self._getFilesWithMetadata(in_dict)

        if not retVal["OK"] and "ExecInfo" in retVal:
            # ExecInfo isn't encodable by DEncode or JEncode and it's normally dropped
            # transparently by the RPC mechanism. As we're doing it by hand here we need
            # to remove it explicitly.
            retVal.pop("ExecInfo")
        fileString = JEncoder.dumps(retVal)

        retVal = fileHelper.stringToNetwork(fileString)
        if not retVal["OK"]:
            self.log.error("Failed to send files:", f"{in_dict}")
            return retVal
        self.log.debug("Sent files for", f"{in_dict} of size {len(fileString)}")
        return S_OK()

    #############################################################################
    @classmethod
    @checkEnoughBKArguments
    def _getFiles(cls, in_dict):
        """It returns a list of files."""
        simdesc = default
        datataking = in_dict.get(
            "SimulationConditions",  # old primary
            in_dict.get("DataTakingConditions", in_dict.get("ConditionDescription", default)),  # old secondary
        )
        procPass = in_dict.get("ProcessingPass", default)
        ftype = in_dict.get("FileType", default)
        evt = in_dict.get("EventType", default)
        configname = in_dict.get("ConfigName", default)
        configversion = in_dict.get("ConfigVersion", default)
        prod = in_dict.get("Production", in_dict.get("ProductionID", default))
        flag = in_dict.get("DataQuality", in_dict.get("DataQualityFlag", default))
        startd = in_dict.get("StartDate", None)
        endd = in_dict.get("EndDate", None)
        nbofevents = in_dict.get("NbOfEvents", False)
        startRunID = in_dict.get("StartRun", None)
        endRunID = in_dict.get("EndRun", None)
        runNbs = in_dict.get("RunNumber", in_dict.get("RunNumbers", []))
        if not isinstance(runNbs, list):
            runNbs = [runNbs]
        replicaFlag = in_dict.get("ReplicaFlag", "Yes")
        visible = in_dict.get("Visible", default)
        filesize = in_dict.get("FileSize", False)
        tck = in_dict.get("TCK", [])
        jobStart = in_dict.get("JobStartDate", None)
        jobEnd = in_dict.get("JobEndDate", None)
        smog2States = in_dict.get("SMOG2", None)
        extendedDQOK = in_dict.get("ExtendedDQOK", None)

        if "ProductionID" in in_dict:
            cls.log.verbose("ProductionID will be removed. It will changed to Production")

        if "DataQualityFlag" in in_dict:
            cls.log.verbose("DataQualityFlag will be removed. It will changed to DataQuality")

        if "RunNumbers" in in_dict:
            cls.log.verbose("RunNumbers will be removed. It will changed to RunNumber")

        retVal = cls.bkkDB.getFiles(
            simdesc,
            datataking,
            procPass,
            ftype,
            evt,
            configname,
            configversion,
            prod,
            flag,
            startd,
            endd,
            nbofevents,
            startRunID,
            endRunID,
            runNbs,
            replicaFlag,
            visible,
            filesize,
            tck,
            jobStart,
            jobEnd,
            smog2States,
            extendedDQOK,
        )
        if not retVal["OK"]:
            return retVal

        return S_OK([i[0] for i in retVal["Value"]])

    #############################################################################
    @classmethod
    @checkEnoughBKArguments
    def _getFilesWithMetadata(cls, in_dict):
        """It returns the files with their metadata."""
        configName = in_dict.get("ConfigName", default)
        configVersion = in_dict.get("ConfigVersion", default)
        conddescription = in_dict.get(
            "ConditionDescription",  # old single
            in_dict.get("SimulationConditions", in_dict.get("DataTakingConditions", default)),
        )
        processing = in_dict.get("ProcessingPass", default)
        evt = in_dict.get("EventType", in_dict.get("EventTypeId", default))
        production = in_dict.get("Production", default)
        filetype = in_dict.get("FileType", default)
        quality = in_dict.get("DataQuality", in_dict.get("DataQualityFlag", in_dict.get("Quality", default)))
        visible = in_dict.get("Visible", "Y")
        replicaFlag = in_dict.get("ReplicaFlag", "Yes")
        startDate = in_dict.get("StartDate", None)
        endDate = in_dict.get("EndDate", None)
        runnumbers = in_dict.get("RunNumber", in_dict.get("RunNumbers", []))
        startRunID = in_dict.get("StartRun", None)
        endRunID = in_dict.get("EndRun", None)
        tcks = in_dict.get("TCK")
        jobStart = in_dict.get("JobStartDate", None)
        jobEnd = in_dict.get("JobEndDate", None)
        smog2States = in_dict.get("SMOG2", None)
        extendedDQOK = in_dict.get("ExtendedDQOK", None)

        method = cls.bkkDB.getFilesWithMetadata
        force_kwargs = {}
        if parameters := in_dict.get("OnlyParameters", None):
            force_kwargs["parameters"] = parameters
        if seed_md5 := in_dict.get("SampleSeedMD5", None):
            force_kwargs["seed_md5"] = seed_md5
        if sample_max := in_dict.get("SampleMax", None):
            force_kwargs["sample_max"] = sample_max

        if force_kwargs:
            # Only the new implementation supports this
            method = partial(cls.bkkDB._newdb.getFilesWithMetadata, **force_kwargs)
        else:
            # TODO: Can be replaced with GETFILESWITHMETADATA_NAME_TO_COL
            parameters = [
                "FileName",
                "EventStat",
                "FileSize",
                "CreationDate",
                "JobStart",
                "JobEnd",
                "WorkerNode",
                "FileType",
                "RunNumber",
                "FillNumber",
                "FullStat",
                "DataqualityFlag",
                "EventInputStat",
                "TotalLuminosity",
                "Luminosity",
                "InstLuminosity",
                "TCK",
                "GUID",
                "ADLER32",
                "EventType",
                "MD5SUM",
                "VisibilityFlag",
                "JobId",
                "GotReplica",
                "InsertTimeStamp",
            ]

        if "EventTypeId" in in_dict:
            cls.log.verbose("The EventTypeId has to be replaced by EventType!")

        if "Quality" in in_dict:
            cls.log.verbose("The Quality has to be replaced by DataQuality!")

        retVal = method(
            configName,
            configVersion,
            conddescription,
            processing,
            evt,
            production,
            filetype,
            quality,
            visible,
            replicaFlag,
            startDate,
            endDate,
            runnumbers,
            startRunID,
            endRunID,
            tcks,
            jobStart,
            jobEnd,
            None,
            smog2States,
            extendedDQOK,
        )
        if not retVal["OK"]:
            return retVal
        records = []
        for record in retVal["Value"]:
            records += [list(record)]
        return S_OK({"ParameterNames": parameters, "Records": records, "TotalRecords": len(records)})

    #############################################################################
    types_getFilesSummary = [dict]

    @checkEnoughBKArguments
    def export_getFilesSummary(self, in_dict):
        """It returns sumary for a given data set.

        Input parameter is a dictionary which has the following keys:
        'ConfigName', 'ConfigVersion', 'ConditionDescription', 'EventType',
        'ProcessingPass','Production','RunNumber', 'FileType', DataQuality
        """
        self.log.debug("Input:", f"{in_dict}")

        configName = in_dict.get("ConfigName", default)
        configVersion = in_dict.get("ConfigVersion", default)
        condDescription = in_dict.get(
            "ConditionDescription",  # old single
            in_dict.get("SimulationConditions", in_dict.get("DataTakingConditions", default)),
        )
        processingPass = in_dict.get("ProcessingPass", default)
        eventType = in_dict.get("EventType", in_dict.get("EventTypeId", default))
        production = in_dict.get("Production", default)
        fileType = in_dict.get("FileType", default)
        dataQuality = in_dict.get("DataQuality", in_dict.get("DataQualityFlag", in_dict.get("Quality", default)))
        startRun = in_dict.get("StartRun", None)
        endRun = in_dict.get("EndRun", None)
        visible = in_dict.get("Visible", "Y")
        startDate = in_dict.get("StartDate", None)
        endDate = in_dict.get("EndDate", None)
        runNumbers = in_dict.get("RunNumber", in_dict.get("RunNumbers", []))
        replicaFlag = in_dict.get("ReplicaFlag", "Yes")
        tcks = in_dict.get("TCK")
        jobStart = in_dict.get("JobStartDate", None)
        jobEnd = in_dict.get("JobEndDate", None)
        smog2States = in_dict.get("SMOG2", None)
        extendedDQOK = in_dict.get("ExtendedDQOK", None)

        if "EventTypeId" in in_dict:
            self.log.verbose("The EventTypeId has to be replaced by EventType!")

        if "Quality" in in_dict:
            self.log.verbose("The Quality has to be replaced by DataQuality!")

        retVal = self.bkkDB.getFilesSummary(
            configName=configName,
            configVersion=configVersion,
            conditionDescription=condDescription,
            processingPass=processingPass,
            eventType=eventType,
            production=production,
            fileType=fileType,
            dataQuality=dataQuality,
            startRun=startRun,
            endRun=endRun,
            visible=visible,
            startDate=startDate,
            endDate=endDate,
            runNumbers=runNumbers,
            replicaFlag=replicaFlag,
            tcks=tcks,
            jobStart=jobStart,
            jobEnd=jobEnd,
            smog2States=smog2States,
            dqok=extendedDQOK,
        )
        if not retVal["OK"]:
            return retVal
        records = []
        parameters = ["NbofFiles", "NumberOfEvents", "FileSize", "Luminosity", "InstLuminosity"]
        for record in retVal["Value"]:
            records += [[record[0], record[1], record[2], record[3], record[4]]]
        return S_OK({"ParameterNames": parameters, "Records": records, "TotalRecords": len(records)})

    #############################################################################
    types_getLimitedFiles = [dict]

    @classmethod
    def export_getLimitedFiles(cls, in_dict):
        """It returns a chunk of files.

        This method is equivalent to the getFiles.
        """
        configName = in_dict.get("ConfigName", default)
        configVersion = in_dict.get("ConfigVersion", default)
        conddescription = in_dict.get(
            "ConditionDescription",  # old single
            in_dict.get("SimulationConditions", in_dict.get("DataTakingConditions", default)),
        )
        processing = in_dict.get("ProcessingPass", default)
        evt = in_dict.get("EventType", in_dict.get("EventTypeId", default))
        production = in_dict.get("Production", default)
        filetype = in_dict.get("FileType", default)
        quality = in_dict.get("DataQuality", in_dict.get("DataQualityFlag", in_dict.get("Quality", default)))
        runnb = in_dict.get("RunNumbers", in_dict.get("RunNumber", default))
        start = in_dict.get("StartItem", 0)
        maxValue = in_dict.get("MaxItem", 10)

        if "EventTypeId" in in_dict:
            cls.log.verbose("The EventTypeId has to be replaced by EventType!")

        if "Quality" in in_dict:
            cls.log.verbose("The Quality has to be replaced by DataQuality!")

        retVal = cls.bkkDB.getLimitedFiles(
            configName,
            configVersion,
            conddescription,
            processing,
            evt,
            production,
            filetype,
            quality,
            runnb,
            start,
            maxValue,
        )
        if not retVal["OK"]:
            return retVal
        records = []
        parameters = [
            "Name",
            "EventStat",
            "FileSize",
            "CreationDate",
            "JobStart",
            "JobEnd",
            "WorkerNode",
            "FileType",
            "EventType",
            "RunNumber",
            "FillNumber",
            "FullStat",
            "DataqualityFlag",
            "EventInputStat",
            "TotalLuminosity",
            "Luminosity",
            "InstLuminosity",
            "TCK",
            "WNMJFHS06",
            "HLT2TCK",
            "NumberOfProcessors",
        ]
        for record in retVal["Value"]:
            records += [
                [
                    record[0],
                    record[1],
                    record[2],
                    str(record[3]),
                    str(record[4]),
                    str(record[5]),
                    record[6],
                    record[7],
                    record[8],
                    record[9],
                    record[10],
                    record[11],
                    record[12],
                    record[13],
                    record[14],
                    record[15],
                    record[16],
                    record[17],
                ]
            ]
        return S_OK({"ParameterNames": parameters, "Records": records, "TotalRecords": len(records)})

    #############################################################################
    types_getAvailableDataQuality = []

    @classmethod
    def export_getAvailableDataQuality(cls):
        """it returns all the available data quality flags."""
        return cls.bkkDB.getAvailableDataQuality()

    #############################################################################
    types_getAvailableExtendedDQOK = []

    @classmethod
    def export_getAvailableExtendedDQOK(cls):
        """it returns all available Exdended DQOK flags."""
        return cls.bkkDB.getAvailableExtendedDQOK()

    #############################################################################
    types_getAvailableSMOG2States = []

    @classmethod
    def export_getAvailableSMOG2States(cls):
        """it returns all available SMOG2 states."""
        return cls.bkkDB.getAvailableSMOG2States()

    #############################################################################
    types_getAvailableProductions = []

    @classmethod
    def export_getAvailableProductions(cls):
        """It returns all the available productions which have associated file with
        replica flag yes."""
        return cls.bkkDB.getAvailableProductions()

    #############################################################################
    types_getAvailableRuns = []

    @classmethod
    def export_getAvailableRuns(cls):
        """It returns all the available runs which have associated files with
        reploica flag yes."""
        return cls.bkkDB.getAvailableRuns()

    #############################################################################
    types_getAvailableEventTypes = []

    @classmethod
    def export_getAvailableEventTypes(cls):
        """It returns all the available event types."""
        return cls.bkkDB.getAvailableEventTypes()

    #############################################################################
    types_getMoreProductionInformations = [int]

    @classmethod
    def export_getMoreProductionInformations(cls, prodid):
        """It returns inforation about a production."""
        return cls.bkkDB.getMoreProductionInformations(prodid)

    #############################################################################
    types_getJobInfo = [str]

    @classmethod
    def export_getJobInfo(cls, lfn):
        """It returns the job metadata information for a given lfn produced by this
        job."""
        return cls.bkkDB.getJobInfo(lfn)

    #############################################################################
    types_bulkJobInfo = [dict]

    @classmethod
    def export_bulkJobInfo(cls, lfns):
        """more info in the BookkeepingClient.py."""
        return cls.bkkDB.bulkJobInfo(lfns)

    #############################################################################
    types_getJobInformation = [dict]

    @classmethod
    def export_getJobInformation(cls, in_dict):
        """It returns the job metadata information for a given lfn produced by this
        job."""
        return cls.bkkDB.getJobInformation(in_dict)

    #############################################################################
    types_getRunNumber = [str]

    @classmethod
    def export_getRunNumber(cls, lfn):
        """It returns the run number for a given lfn!"""
        return cls.bkkDB.getRunNumber(lfn)

    #############################################################################
    types_getRunNbAndTck = [str]

    @classmethod
    def export_getRunNbAndTck(cls, lfn):
        """It returns the run number and tck for a given LFN."""
        return cls.bkkDB.getRunNbAndTck(lfn)

    #############################################################################
    types_getProductionFiles = [int, str]

    @classmethod
    def export_getProductionFiles(cls, prod, fileType, replica=default):
        """It returns files and their metadata for a given production, file type
        and replica."""
        return cls.bkkDB.getProductionFiles(prod, fileType, replica)

    #############################################################################
    types_getProductionFilesBulk = [list, (str, list)]

    @classmethod
    def export_getProductionFilesBulk(cls, prods, fileType, replica=default):
        """It returns files and their metadata for list of productions, file type
        and replica."""
        return cls.bkkDB.getProductionFilesBulk(prods, fileType, replica)

    #############################################################################
    types_getAvailableRunNumbers = []

    def export_getAvailableRunNumbers(self):
        """more info in the BookkeepingClient.py."""
        return self.export_getAvailableRuns()

    #############################################################################
    types_getRunFiles = [int]

    @classmethod
    def export_getRunFiles(cls, runid):
        """It returns all the files and their metadata for a given run number!"""
        return cls.bkkDB.getRunFiles(runid)

    #############################################################################
    types_updateFileMetaData = [str, dict]

    @classmethod
    def export_updateFileMetaData(cls, filename, fileAttr):
        """This method used to modify files metadata.

        Input parametes is a stirng (filename) and a dictionary (fileAttr)
        with the file attributes. {'GUID':34826386286382,'EventStat':222222}
        """
        return cls.bkkDB.updateFileMetaData(filename, fileAttr)

    #############################################################################
    types_renameFile = [str, str]

    @classmethod
    def export_renameFile(cls, oldLFN, newLFN):
        """It allows to change the name of a file which is in the Bookkeeping
        Metadata Catalogue."""
        return cls.bkkDB.renameFile(oldLFN, newLFN)

    #############################################################################
    types_getProductionProcessingPassID = [int]

    @classmethod
    def export_getProductionProcessingPassID(cls, prodid):
        """more info in the BookkeepingClient.py."""
        return cls.bkkDB.getProductionProcessingPassID(prodid)

    #############################################################################
    types_getProductionProcessingPass = [int]

    @classmethod
    def export_getProductionProcessingPass(cls, prodid):
        """It returns the processing pass for a given production."""
        return cls.bkkDB.getProductionProcessingPass(prodid)

    #############################################################################
    types_insertTag = [dict]

    @classmethod
    def export_insertTag(cls, values):
        """It used to register tags (CONDB, DDDB, etc) to the database.

        The input parameter is dictionary: {'TagName':'Value'}
        """
        successful = {}
        failed = {}

        for i in values:
            tags = values[i]
            for tag in tags:
                retVal = cls.bkkDB.existsTag(i, tag)
                if retVal["OK"] and not retVal["Value"]:
                    retVal = cls.bkkDB.insertTag(i, tag)
                    if not retVal["OK"]:
                        failed[tag] = i
                    else:
                        successful[tag] = i
                else:
                    failed[tag] = i
        return S_OK({"Successful": successful, "Failed": failed})

    #############################################################################
    types_setFileDataQuality = [list, str]

    @classmethod
    def export_setFileDataQuality(cls, lfns, flag):
        """more info in the BookkeepingClient.py."""
        return cls.bkkDB.setFileDataQuality(lfns, flag)

    #############################################################################
    types_setRunAndProcessingPassDataQuality = [int, str, str]

    @classmethod
    def export_setRunAndProcessingPassDataQuality(cls, runNB, procpass, flag):
        """It sets the data quality to a run which belong to a given processing
        pass.

        This method insert a new row to the runquality table. This value
        used to set the data quality flag to a given run files which
        processed by a given processing pass.
        """
        return cls.bkkDB.setRunAndProcessingPassDataQuality(runNB, procpass, flag)

    #############################################################################
    types_setRunDataQuality = [int, str]

    @classmethod
    def export_setRunDataQuality(cls, runNb, flag):
        """It sets the data quality for a given run!

        The input parameter is the run number and a data quality flag.
        """
        return cls.bkkDB.setRunDataQuality(runNb, flag)

    #############################################################################
    types_setExtendedDQOK = [int, bool, list]

    @classmethod
    def export_setExtendedDQOK(cls, runNB, update, dqok):
        """For given run insert or update the list of Systems which are OK
        NOTE: this call is priviledged
        """
        return cls.bkkDB.setExtendedDQOK(runNB, update, dqok)

    #############################################################################
    types_setProductionDataQuality = [int, str]

    @classmethod
    def export_setProductionDataQuality(cls, prod, flag):
        """It sets the data quality for a given production!"""
        return cls.bkkDB.setProductionDataQuality(prod, flag)

    #############################################################################
    types_getFileAncestors = [list, int, bool]

    @classmethod
    def export_getFileAncestors(cls, lfns, depth=None, replica=None):
        """more info in the BookkeepingClient.py."""
        return cls.bkkDB.getFileAncestors(lfns, depth, replica)

    #############################################################################
    types_getAncestors = [list, int]

    @classmethod
    def export_getAncestors(cls, lfns, depth):
        """Get the ancestors for a list of LFNs in input"""
        retVal = cls.bkkDB.getFileAncestors(lfns, depth, True)
        if not retVal["OK"]:
            return retVal
        values = retVal["Value"]
        for key, value in values["Successful"].items():
            values["Successful"][key] = [i["FileName"] for i in value]
        return S_OK(values)

    #############################################################################
    types_getFileDescendents = [list, int, int, bool]

    @classmethod
    def export_getFileDescendents(cls, lfn, depth, production=0, checkreplica=True):
        """more info in the BookkeepingClient.py."""
        return cls.bkkDB.getFileDescendents(lfn, depth, production, checkreplica)

    #############################################################################
    types_getFileDescendants = [list, int, int, bool]

    @deprecated("Use getFileDescendents")
    def export_getFileDescendants(self, lfn, depth, production=0, checkreplica=True):
        """more info in the BookkeepingClient.py."""
        return self.export_getFileDescendents(lfn, depth, production, checkreplica)

    #############################################################################
    types_checkfile = [str]

    @classmethod
    def export_checkfile(cls, fileName):
        """more info in the BookkeepingClient.py."""
        return cls.bkkDB.checkfile(fileName)

    #############################################################################
    types_checkFileTypeAndVersion = [str, str]

    @classmethod
    def export_checkFileTypeAndVersion(cls, ftype, version):
        """more info in the BookkeepingClient.py."""
        return cls.bkkDB.checkFileTypeAndVersion(ftype, version)

    #############################################################################
    types_checkEventType = [int]

    @classmethod
    def export_checkEventType(cls, eventTypeId):
        """more info in the BookkeepingClient.py."""
        if eventTypeId not in cls.__eventTypeCache:
            retVal = cls.bkkDB.checkEventType(eventTypeId)
            if not retVal["OK"]:
                return retVal
            cls.__eventTypeCache[eventTypeId] = retVal

        return cls.__eventTypeCache[eventTypeId]

    #############################################################################
    types_insertSimConditions = [dict]

    @classmethod
    def export_insertSimConditions(cls, in_dict):
        """It inserts a simulation condition to the Bookkeeping Metadata
        catalogue."""
        return cls.bkkDB.insertSimConditions(in_dict)

    #############################################################################
    types_getSimConditions = []

    @classmethod
    def export_getSimConditions(cls):
        """It returns all the simulation conditions which are in the Bookkeeping
        Metadata catalogue."""
        return cls.bkkDB.getSimConditions()

    #############################################################################
    types_removeReplica = [str]

    @classmethod
    def export_removeReplica(cls, fileName):
        """more info in the BookkeepingClient.py."""
        return cls.bkkDB.removeReplica(fileName)

    #############################################################################
    types_getFileMetadata = [list]

    @classmethod
    def export_getFileMetadata(cls, lfns):
        """more info in the BookkeepingClient.py."""
        return cls.bkkDB.getFileMetadata(lfns)

    #############################################################################
    types_getProductionFilesForWeb = [int, dict, dict, int, int]

    @classmethod
    def export_getProductionFilesWeb(cls, prod, ftype, sortDict, startItem, maxitems):
        """It returns files and their metadata information for a given
        production."""
        return cls.bkkDB.getProductionFilesForWeb(prod, ftype, sortDict, startItem, maxitems)

    #############################################################################
    types_exists = [list]

    @classmethod
    def export_exists(cls, lfns):
        """more info in the BookkeepingClient.py."""
        return cls.bkkDB.exists(lfns)

    #############################################################################
    types_addReplica = [list]

    @classmethod
    def export_addReplica(cls, fileName):
        """more info in the BookkeepingClient.py."""
        return cls.bkkDB.addReplica(fileName)

    #############################################################################
    types_getRunInformations = [int]

    @classmethod
    def export_getRunInformations(cls, runnb):
        """It returns run information and statistics."""
        return cls.bkkDB.getRunInformations(runnb)

    #############################################################################
    types_getRunInformation = [dict]

    @classmethod
    def export_getRunInformation(cls, runnb):
        """more info in the BookkeepingClient.py."""
        return cls.bkkDB.getRunInformation(runnb)

    #############################################################################
    types_getFileCreationLog = [str]

    @classmethod
    def export_getFileCreationLog(cls, lfn):
        """For a given file returns the log files of the job which created it."""
        return cls.bkkDB.getFileCreationLog(lfn)

    #############################################################################
    types_insertEventType = [int, str, str]

    @classmethod
    def export_insertEventType(cls, evid, desc, primary):
        """It inserts an event type to the Bookkeeping Metadata catalogue."""
        retVal = cls.bkkDB.checkEventType(evid)
        if not retVal["OK"]:  # meaning the event type is not already inserted
            retVal = cls.bkkDB.insertEventTypes(evid, desc, primary)
            if not retVal["OK"]:
                return retVal
            return S_OK(str(evid) + " event type added successfully!")
        return S_OK(str(evid) + " event type exists")

    #############################################################################
    types_updateEventType = [int, str, str]

    @classmethod
    def export_updateEventType(cls, evid, desc, primary):
        """It can used to modify an existing event type."""

        retVal = cls.bkkDB.checkEventType(evid)
        if not retVal["OK"]:
            return S_ERROR(str(evid) + " event type is missing in the BKK database!")

        retVal = cls.bkkDB.updateEventType(evid, desc, primary)
        if not retVal["OK"]:
            return retVal
        return S_OK(str(evid) + " event type updated successfully!")

    #############################################################################
    types_addFiles = [list]

    @classmethod
    def export_addFiles(cls, lfns):
        """more info in the BookkeepingClient.py."""
        return cls.bkkDB.addReplica(lfns)

    #############################################################################
    types_removeFiles = [list]

    @classmethod
    def export_removeFiles(cls, lfns):
        """more info in the BookkeepingClient.py."""
        return cls.bkkDB.removeReplica(lfns)

    #############################################################################
    types_getProductionSummary = [dict]

    @classmethod
    def export_getProductionSummary(cls, in_dict):
        """It can used to count the number of events for a given dataset."""

        cName = in_dict.get("ConfigName", default)
        cVersion = in_dict.get("ConfigVersion", default)
        production = in_dict.get("Production", default)
        simdesc = in_dict.get(
            "ConditionDescription",  # old single
            in_dict.get("SimulationConditions", in_dict.get("DataTakingConditions", default)),
        )
        pgroup = in_dict.get("ProcessingPass", default)
        ftype = in_dict.get("FileType", default)
        evttype = in_dict.get("EventType", default)
        return cls.bkkDB.getProductionSummary(cName, cVersion, simdesc, pgroup, production, ftype, evttype)

    #############################################################################
    types_getProductionInformation = [int]

    def export_getProductionInformation(self, prodid):
        """It returns statistics (data processing phases, number of events, etc.) for a given production.

        NOTE: This method is EXTREMELY slow and should be used with caution.
        NOTE: The returned paths are incorrect if we have no files GotReplica=True
        """

        nbjobs = None
        nbOfFiles = None
        nbOfEvents = None
        prodinfos = None

        value = self.bkkDB.getProductionNbOfJobs(prodid)
        if value["OK"]:
            nbjobs = value["Value"]

        value = self.bkkDB.getProductionNbOfFiles(prodid)
        if value["OK"]:
            nbOfFiles = value["Value"]

        value = self.bkkDB.getProductionNbOfEvents(prodid)
        if value["OK"]:
            nbOfEvents = value["Value"]

        value = self.bkkDB.getConfigsAndEvtType(prodid)
        if value["OK"]:
            prodinfos = value["Value"]

        path = "/"

        if not prodinfos:
            self.log.error("No Configs/Event type for production", prodid)
            return S_ERROR("No Configs/Event type")

        cname = prodinfos[0][0]
        cversion = prodinfos[0][1]
        path += cname + "/" + cversion + "/"

        res = self.bkkDB.getProductionSimulationCond(prodid)
        if not res["OK"]:
            return res
        path += res["Value"]

        res = self.bkkDB.getProductionProcessingPass(prodid)
        if not res["OK"]:
            return res
        path += res["Value"]
        prefix = "\n" + path

        # At this point prefix is of the form '\n/ConfigName/ConfigVersion/SimulationConditions/ProcessingPass'
        # We now iterate over nbOfEvents to get the paths containing the eventtype and filetype.
        # Each path is separated by a newline character.
        for filetype, _, eventtype, _ in nbOfEvents:
            path += prefix + "/" + str(eventtype) + "/" + filetype
        result = {
            "Production information": prodinfos,
            "Number of jobs": nbjobs,
            "Number of files": nbOfFiles,
            "Number of events": nbOfEvents,
            "Path": path,
        }
        return S_OK(result)

    #############################################################################
    types_getOutputPathsForProdID = [int]

    @convertToReturnValue
    def export_getOutputPathsForProdID(self, prodID):
        """It returns the file types for a given production."""

        configs = returnValueOrRaise(self.bkkDB.getConfigsAndEvtType(prodID))
        conddesc = returnValueOrRaise(self.bkkDB.getProductionSimulationCond(prodID))
        procpass = returnValueOrRaise(self.bkkDB.getProductionProcessingPass(prodID))
        filetypes = returnValueOrRaise(self.bkkDB.getFileTypesForProdID(prodID))
        paths = []
        for config_name, config_version, eventtype in configs:
            paths.extend(
                f"/{config_name}/{config_version}/{conddesc}{procpass}/{eventtype}/{filetype}" for filetype in filetypes
            )
        return paths

    #############################################################################
    types_getFileHistory = [str]

    @classmethod
    def export_getFileHistory(cls, lfn):
        """It returns all the information about a file."""
        retVal = cls.bkkDB.getFileHistory(lfn)
        result = {}
        records = []
        if retVal["OK"]:
            values = retVal["Value"]
            parameterNames = [
                "FileId",
                "FileName",
                "ADLER32",
                "CreationDate",
                "EventStat",
                "Eventtype",
                "Gotreplica",
                "GUI",
                "JobId",
                "md5sum",
                "FileSize",
                "FullStat",
                "Dataquality",
                "FileInsertDate",
                "Luminosity",
                "InstLuminosity",
            ]
            counter = 0
            for record in values:
                value = [
                    record[0],
                    record[1],
                    record[2],
                    record[3],
                    record[4],
                    record[5],
                    record[6],
                    record[7],
                    record[8],
                    record[9],
                    record[10],
                    record[11],
                    record[12],
                    record[13],
                    record[14],
                    record[15],
                ]
                records += [value]
                counter += 1
            result = {"ParameterNames": parameterNames, "Records": records, "TotalRecords": counter}
        else:
            result = S_ERROR(retVal["Message"])
        return S_OK(result)

    #############################################################################
    types_getJobsNb = [int]

    @classmethod
    @deprecated("Use getProductionNbOfJobs")
    def export_getJobsNb(cls, prodid):
        """more info in the BookkeepingClient.py."""
        return cls.bkkDB.getProductionNbOfJobs(prodid)

    #############################################################################
    types_getProductionNbOfJobs = [int]

    @classmethod
    def export_getProductionNbOfJobs(cls, prodid):
        """It returns the number of jobs for a given production."""
        return cls.bkkDB.getProductionNbOfJobs(prodid)

    #############################################################################
    types_getNumberOfEvents = [int]

    @classmethod
    @deprecated("Use getProductionNbOfEvents")
    def export_getNumberOfEvents(cls, prodid):
        """more info in the BookkeepingClient.py."""
        return cls.bkkDB.getProductionNbOfEvents(prodid)

    #############################################################################
    types_getProductionNbOfEvents = [int]

    @classmethod
    def export_getProductionNbOfEvents(cls, prodid):
        """It returns the number of events for a given production."""
        return cls.bkkDB.getProductionNbOfEvents(prodid)

    #############################################################################
    types_getSizeOfFiles = [int]

    @classmethod
    @deprecated("Use getProductionSizeOfFiles")
    def export_getSizeOfFiles(cls, prodid):
        """more info in the BookkeepingClient.py."""
        return cls.bkkDB.getProductionSizeOfFiles(prodid)

    #############################################################################
    types_getProductionSizeOfFiles = [int]

    @classmethod
    def export_getProductionSizeOfFiles(cls, prodid):
        """It returns the size of files for a given production."""
        return cls.bkkDB.getProductionSizeOfFiles(prodid)

    #############################################################################
    types_getNbOfFiles = [int]

    @classmethod
    @deprecated("Use getProductionNbOfFiles")
    def export_getNbOfFiles(cls, prodid):
        """more info in the BookkeepingClient.py."""
        return cls.bkkDB.getProductionNbOfFiles(prodid)

    #############################################################################
    types_getProductionNbOfFiles = [int]

    @classmethod
    def export_getProductionNbOfFiles(cls, prodid):
        """It returns the number of files produced by a given production."""
        return cls.bkkDB.getProductionNbOfFiles(prodid)

    #############################################################################
    types_getNbOfJobsBySites = [int]

    @classmethod
    def export_getNbOfJobsBySites(cls, prodid):
        """It returns the number of jobs executed at different sites for a given
        production."""
        return cls.bkkDB.getNbOfJobsBySites(prodid)

    #############################################################################
    types_getAvailableTags = []

    @classmethod
    def export_getAvailableTags(cls):
        """It returns the available database tags."""
        return cls.bkkDB.getAvailableTags()

    #############################################################################
    types_getProcessedEvents = [int]

    @classmethod
    @deprecated("Use getProductionProcessedEvents")
    def export_getProcessedEvents(cls, prodid):
        """more info in the BookkeepingClient.py."""
        return cls.bkkDB.getProductionProcessedEvents(prodid)

    #############################################################################
    types_getProductionProcessedEvents = [int]

    @classmethod
    def export_getProductionProcessedEvents(cls, prodid):
        """it returns the number of events processed for a given production."""
        cls.log.debug("getProductionProcessedEvents->Production:", "%d " % prodid)
        return cls.bkkDB.getProductionProcessedEvents(prodid)

    #############################################################################
    types_getRunsForAGivenPeriod = [dict]

    @classmethod
    def export_getRunsForAGivenPeriod(cls, in_dict):
        """It returns the available runs between a period.

        Input parameters:
        AllowOutsideRuns: If it is true, it only returns the runs which finished before EndDate.
        StartDate: the run start period
        EndDate: the run end period
        """
        return cls.bkkDB.getRunsForAGivenPeriod(in_dict)

    #############################################################################
    types_getProductionsFromView = [dict]

    @classmethod
    @deprecated("Useless?")
    def export_getProductionsFromView(cls, in_dict):
        """It returns the productions from the bookkeeping view for a given
        processing pass and run number.

        Input parameters: RunNumber ProcessingPass
        """
        # FIXME: might be a useless method
        return cls.bkkDB.getProductionsFromView(in_dict)

    #############################################################################
    types_getRunFilesDataQuality = [list]

    @classmethod
    def export_getRunFilesDataQuality(cls, runs):
        """more info in the BookkeepingClient.py."""
        return cls.bkkDB.getRunFilesDataQuality(runs)

    #############################################################################
    types_getRunExtendedDQOK = [int]

    @classmethod
    def export_getRunExtendedDQOK(cls, runNB):
        """Return the list of systems in ExtendedDQOK for given run"""
        return cls.bkkDB.getRunExtendedDQOK(runNB)

    #############################################################################
    types_setFilesInvisible = [list]

    @classmethod
    def export_setFilesInvisible(cls, lfns):
        """more info in the BookkeepingClient.py."""
        return cls.bkkDB.setFilesInvisible(lfns)

    #############################################################################
    types_setFilesVisible = [list]

    @classmethod
    def export_setFilesVisible(cls, lfns):
        """more info in the BookkeepingClient.py."""
        return cls.bkkDB.setFilesVisible(lfns)

    #############################################################################
    types_getRunAndProcessingPassDataQuality = [int, int]

    @classmethod
    def export_getRunAndProcessingPassDataQuality(cls, runnb, processing):
        """It returns the data quality flag for a given run and processing pass."""
        return cls.bkkDB.getRunAndProcessingPassDataQuality(runnb, processing)

    #############################################################################
    types_getAvailableConfigurations = []

    @classmethod
    def export_getAvailableConfigurations(cls):
        """It returns the available configurations."""
        return cls.bkkDB.getAvailableConfigurations()

    #############################################################################
    types_getRunProcessingPass = [int]

    @classmethod
    def export_getRunProcessingPass(cls, runnumber):
        """it returns the run number for a given run."""
        return cls.bkkDB.getRunProcessingPass(runnumber)

    #############################################################################
    types_getProductionFilesStatus = [int, list]

    @classmethod
    def export_getProductionFilesStatus(cls, productionid=None, lfns=None):
        """It returns the file status in the bkk for a given production or a list
        of lfns."""
        if not lfns:
            lfns = []
        return cls.bkkDB.getProductionFilesStatus(productionid, lfns)

    #############################################################################
    types_getFiles = [dict]

    @classmethod
    def export_getFiles(cls, values):
        """more info in the BookkeepingClient.py."""

        simdesc = default
        datataking = values.get(
            "SimulationConditions",  # old primary
            values.get("DataTakingConditions", values.get("ConditionDescription", default)),  # old secondary
        )
        procPass = values.get("ProcessingPass", default)
        ftype = values.get("FileType", default)
        evt = values.get("EventType", 0)
        configname = values.get("ConfigName", default)
        configversion = values.get("ConfigVersion", default)
        prod = values.get("Production", values.get("ProductionID", default))
        flag = values.get("DataQuality", values.get("DataQualityFlag", default))
        startd = values.get("StartDate", None)
        endd = values.get("EndDate", None)
        nbofevents = values.get("NbOfEvents", False)
        startRunID = values.get("StartRun", None)
        endRunID = values.get("EndRun", None)
        runNbs = values.get("RunNumber", values.get("RunNumbers", []))
        if not isinstance(runNbs, list):
            runNbs = [runNbs]
        replicaFlag = values.get("ReplicaFlag", "Yes")
        visible = values.get("Visible", default)
        filesize = values.get("FileSize", False)
        tck = values.get("TCK")
        jobStart = values.get("JobStartDate", None)
        jobEnd = values.get("JobEndDate", None)

        if "ProductionID" in values:
            cls.log.verbose("ProductionID will be removed. It will changed to Production")

        if "DataQualityFlag" in values:
            cls.log.verbose("DataQualityFlag will be removed. It will changed to DataQuality")

        if "RunNumbers" in values:
            cls.log.verbose("RunNumbers will be removed. It will changed to RunNumber")

        result = []
        retVal = cls.bkkDB.getFiles(
            simdesc,
            datataking,
            procPass,
            ftype,
            evt,
            configname,
            configversion,
            prod,
            flag,
            startd,
            endd,
            nbofevents,
            startRunID,
            endRunID,
            runNbs,
            replicaFlag,
            visible,
            filesize,
            tck,
            jobStart,
            jobEnd,
        )
        if not retVal["OK"]:
            return retVal
        values = retVal["Value"]
        for i in values:
            result += [i[0]]

        return S_OK(result)

    #############################################################################
    types_getFilesWithGivenDataSetsForUsers = [dict]

    def export_getFilesWithGivenDataSetsForUsers(self, values):
        """more info in the BookkeepingClient.py."""
        return self.export_getVisibleFilesWithMetadata(values)

    #############################################################################
    types_getVisibleFilesWithMetadata = [dict]

    @classmethod
    def export_getVisibleFilesWithMetadata(cls, in_dict):
        """It returns a list of files with metadata for a given condition."""

        conddescription = in_dict.get(
            "SimulationConditions",  # old primary
            in_dict.get("DataTakingConditions", in_dict.get("ConditionDescription", default)),  # old secondary
        )
        procPass = in_dict.get("ProcessingPass", default)
        ftype = in_dict.get("FileType", default)
        evt = in_dict.get("EventType", default)
        configname = in_dict.get("ConfigName", default)
        configversion = in_dict.get("ConfigVersion", default)
        prod = in_dict.get("Production", in_dict.get("ProductionID", default))
        dqflag = in_dict.get("DataQuality", in_dict.get("DataQualityFlag", default))
        startd = in_dict.get("StartDate", None)
        endd = in_dict.get("EndDate", None)
        startRunID = in_dict.get("StartRun", None)
        endRunID = in_dict.get("EndRun", None)
        runNbs = in_dict.get("RunNumber", in_dict.get("RunNumbers", []))
        replicaFlag = in_dict.get("ReplicaFlag", "Yes")
        tck = in_dict.get("TCK", [])
        visible = in_dict.get("Visible", "Y")
        jobStart = in_dict.get("JobStartDate", None)
        jobEnd = in_dict.get("JobEndDate", None)
        smog2States = in_dict.get("SMOG2", None)
        extendedDQOK = in_dict.get("ExtendedDQOK", None)

        if ftype == default:
            return S_ERROR("FileType is missing!")

        if "ProductionID" in in_dict:
            cls.log.verbose("ProductionID will be removed. It will changed to Production")

        if "DataQualityFlag" in in_dict:
            cls.log.verbose("DataQualityFlag will be removed. It will changed to DataQuality")

        if "RunNumbers" in in_dict:
            cls.log.verbose("RunNumbers will be removed. It will changed to RunNumber")

        cls.log.debug("getVisibleFilesWithMetadata->", str(in_dict))
        result = {}
        retVal = cls.bkkDB.getFilesWithMetadata(
            configName=configname,
            configVersion=configversion,
            conddescription=conddescription,
            processing=procPass,
            evt=evt,
            production=prod,
            filetype=ftype,
            quality=dqflag,
            visible=visible,
            replicaflag=replicaFlag,
            startDate=startd,
            endDate=endd,
            runnumbers=runNbs,
            startRunID=startRunID,
            endRunID=endRunID,
            tcks=tck,
            jobStart=jobStart,
            jobEnd=jobEnd,
            smog2States=smog2States,
            dqok=extendedDQOK,
        )

        summary = 0

        parameters = [
            "FileName",
            "EventStat",
            "FileSize",
            "CreationDate",
            "JobStart",
            "JobEnd",
            "WorkerNode",
            "FileType",
            "RunNumber",
            "FillNumber",
            "FullStat",
            "DataqualityFlag",
            "EventInputStat",
            "TotalLuminosity",
            "Luminosity",
            "InstLuminosity",
            "TCK",
            "GUID",
            "ADLER32",
            "EventType",
            "MD5SUM",
            "VisibilityFlag",
            "JobId",
            "GotReplica",
            "InsertTimeStamp",
        ]

        if not retVal["OK"]:
            return retVal

        values = retVal["Value"]
        nbfiles = 0
        nbevents = 0
        evinput = 0
        fsize = 0
        tLumi = 0
        lumi = 0
        ilumi = 0
        for i in values:
            nbfiles = nbfiles + 1
            row = dict(zip(parameters, i))
            if row["EventStat"] is not None:
                nbevents += row["EventStat"]
            if row["EventInputStat"] is not None:
                evinput += row["EventInputStat"]
            if row["FileSize"] is not None:
                fsize += row["FileSize"]
            if row["TotalLuminosity"] is not None:
                tLumi += row["TotalLuminosity"]
            if row["Luminosity"] is not None:
                lumi += row["Luminosity"]
            if row["InstLuminosity"] is not None:
                ilumi += row["InstLuminosity"]
            result[row["FileName"]] = {
                "EventStat": row["EventStat"],
                "EventInputStat": row["EventInputStat"],
                "Runnumber": row["RunNumber"],
                "Fillnumber": row["FillNumber"],
                "FileSize": row["FileSize"],
                "TotalLuminosity": row["TotalLuminosity"],
                "Luminosity": row["Luminosity"],
                "InstLuminosity": row["InstLuminosity"],
                "TCK": row["TCK"],
            }
        if nbfiles > 0:
            summary = {
                "Number Of Files": nbfiles,
                "Number of Events": nbevents,
                "EventInputStat": evinput,
                "FileSize": fsize / 1e9,
                "TotalLuminosity": tLumi,
                "Luminosity": lumi,
                "InstLuminosity": ilumi,
            }
        return S_OK({"LFNs": result, "Summary": summary})

    #############################################################################
    types_addProduction = [dict]

    @classmethod
    def export_addProduction(cls, infos):
        """It is used to register a production in the bkk.

        Input parameters:
        SimulationConditions
        DataTakingConditions
        Steps: the step which is used to process data for a given production.
        Production:
        InputProductionTotalProcessingPass: it is a path of the input data processing pass
        """

        cls.log.debug("Registering:", infos)
        simcond = infos.get("SimulationConditions", None)
        daqdesc = infos.get("DataTakingConditions", None)
        production = None

        if simcond is None and daqdesc is None:
            return S_ERROR("SimulationConditions and DataTakingConditions are both missing!")

        if "Steps" not in infos:
            return S_ERROR("Missing Steps!")
        if "Production" not in infos:
            return S_ERROR("Production is missing!")
        if "EventType" not in infos:
            return S_ERROR("EventType is missing!")

        steps = infos["Steps"]
        inputProdTotalProcessingPass = ""
        production = infos["Production"]
        inputProdTotalProcessingPass = infos.get("InputProductionTotalProcessingPass", "")
        configName = infos.get("ConfigName")
        configVersion = infos.get("ConfigVersion")
        eventType = infos.get("EventType")
        return cls.bkkDB.addProduction(
            production=production,
            simcond=simcond,
            daq=daqdesc,
            steps=steps,
            inputproc=inputProdTotalProcessingPass,
            configName=configName,
            configVersion=configVersion,
            eventType=eventType,
        )

    #############################################################################
    types_getEventTypes = [dict]

    @classmethod
    def export_getEventTypes(cls, in_dict):
        """It returns the available event types for a given configuration name and
        configuration version.

        Input parameters: ConfigName, ConfigVersion, Production
        """

        configName = in_dict.get("ConfigName", default)
        configVersion = in_dict.get("ConfigVersion", default)
        production = in_dict.get("Production", default)
        return cls.bkkDB.getEventTypes(configName, configVersion, production)

    #############################################################################
    types_getProcessingPassSteps = [dict]

    @classmethod
    def export_getProcessingPassSteps(cls, in_dict):
        """It returns the steps for a given stepname, processing pass and
        production."""
        stepname = in_dict.get("StepName", default)
        cond = in_dict.get(
            "ConditionDescription",  # old single
            in_dict.get("SimulationConditions", in_dict.get("DataTakingConditions", default)),
        )
        procpass = in_dict.get("ProcessingPass", default)

        return cls.bkkDB.getProcessingPassSteps(procpass, cond, stepname)

    #############################################################################
    types_getProductionProcessingPassSteps = [dict]

    @classmethod
    def export_getProductionProcessingPassSteps(cls, in_dict):
        """it returns the steps for a given production."""

        if "Production" in in_dict:
            return cls.bkkDB.getProductionProcessingPassSteps(in_dict["Production"])
        return S_ERROR("The Production dictionary key is missing!!!")

    #############################################################################
    types_getProductionOutputFiles = [dict]

    @deprecated("Use getProductionOutputFileTypes")
    def export_getProductionOutputFiles(self, in_dict):
        """more info in the BookkeepingClient.py."""

        return self.export_getProductionOutputFileTypes(in_dict)

    #############################################################################
    types_getProductionOutputFileTypes = [dict]

    @classmethod
    def export_getProductionOutputFileTypes(cls, in_dict):
        """It returns the output file types which produced by a given
        production."""

        production = in_dict.get("Production", default)
        stepid = in_dict.get("StepId", default)

        if production != default:
            return cls.bkkDB.getProductionOutputFileTypes(production, stepid)
        return S_ERROR("The Production dictionary key is missing!!!")

    #############################################################################
    types_getRunQuality = [str, str]

    @deprecated("Use getRunWithProcessingPassAndDataQuality")
    def export_getRunQuality(self, procpass, flag=default):
        """more info in the BookkeepingClient.py."""

        return self.export_getRunWithProcessingPassAndDataQuality(procpass, flag)

    #############################################################################
    types_getRunWithProcessingPassAndDataQuality = [str, str]

    @classmethod
    def export_getRunWithProcessingPassAndDataQuality(cls, procpass, flag=default):
        """It returns the run number for a given processing pass and a flag from
        the run quality table."""
        return cls.bkkDB.getRunWithProcessingPassAndDataQuality(procpass, flag)

    #############################################################################
    types_getRuns = [dict]

    @classmethod
    def export_getRuns(cls, in_dict):
        """It returns the runs for a given configuration name and version.

        Input parameters:
        """
        cName = in_dict.get("ConfigName", default)
        cVersion = in_dict.get("ConfigVersion", default)
        if cName != default and cVersion != default:
            return cls.bkkDB.getRuns(cName, cVersion)
        return S_ERROR("The configuration name and version have to be defined!")

    #############################################################################
    types_getRunProcPass = [dict]

    def export_getRunProcPass(self, in_dict):
        """more info in the BookkeepingClient.py."""
        return self.export_getRunAndProcessingPass(in_dict)

    #############################################################################
    types_getRunAndProcessingPass = [dict]

    @classmethod
    def export_getRunAndProcessingPass(cls, in_dict):
        """It returns all the processing pass and run number for a given run."""
        run = in_dict.get("RunNumber", default)
        if run != default:
            return cls.bkkDB.getRunAndProcessingPass(run)
        return S_ERROR("The run number has to be specified!")

    #############################################################################
    types_getProcessingPassId = [str]

    @classmethod
    def export_getProcessingPassId(cls, fullpath):
        """It returns the ProcessingPassId for a given path.

        this method should not used!
        """
        return cls.bkkDB.getProcessingPassId(fullpath)

    #############################################################################
    types_getRunNbFiles = [dict]

    @deprecated("Use getNbOfRawFiles")
    def export_getRunNbFiles(self, in_dict):
        """more info in the BookkeepingClient.py."""
        return self.export_getNbOfRawFiles(in_dict)

    #############################################################################
    types_getNbOfRawFiles = [dict]

    @classmethod
    def export_getNbOfRawFiles(cls, in_dict):
        """It counts the raw files for a given run and (or) event type."""

        runnb = in_dict.get("RunNumber", default)
        evt = in_dict.get("EventType", in_dict.get("EventTypeId", default))
        if "EventTypeId" in in_dict:
            cls.log.verbose("The EventTypeId has to be replaced by EventType!")

        replicaFlag = in_dict.get("ReplicaFlag", "Yes")
        visible = in_dict.get("Visible", "Y")
        isFinished = in_dict.get("Finished", "ALL")
        if runnb == default and evt == default:
            return S_ERROR("Run number or event type must be given!")
        retVal = cls.bkkDB.getNbOfRawFiles(runnb, evt, replicaFlag, visible, isFinished)
        if not retVal["OK"]:
            return retVal
        return S_OK(retVal["Value"][0][0])

    #############################################################################
    types_getTypeVersion = [list]

    def export_getTypeVersion(self, lfn):
        """more info in the BookkeepingClient.py."""
        return self.export_getFileTypeVersion(lfn)

    #############################################################################
    types_getFileTypeVersion = [list]

    @classmethod
    def export_getFileTypeVersion(cls, lfn):
        """more info in the BookkeepingClient.py."""
        return cls.bkkDB.getFileTypeVersion(lfn)

    #############################################################################
    types_getTCKs = [dict]

    @classmethod
    def export_getTCKs(cls, in_dict):
        """It returns the tcks for a given data set."""
        configName = in_dict.get("ConfigName", default)
        configVersion = in_dict.get("ConfigVersion", default)
        conddescription = in_dict.get(
            "ConditionDescription",  # old single
            in_dict.get("SimulationConditions", in_dict.get("DataTakingConditions", default)),
        )
        processing = in_dict.get("ProcessingPass", default)
        evt = in_dict.get("EventType", in_dict.get("EventTypeId", default))
        production = in_dict.get("Production", default)
        filetype = in_dict.get("FileType", default)
        quality = in_dict.get("DataQuality", in_dict.get("DataQualityFlag", in_dict.get("Quality", default)))
        runnb = in_dict.get("RunNumber", default)
        if "Quality" in in_dict:
            cls.log.verbose("The Quality has to be replaced by DataQuality!")

        if "EventTypeId" in in_dict:
            cls.log.verbose("The EventTypeId has to be replaced by EventType!")

        retVal = cls.bkkDB.getTCKs(
            configName, configVersion, conddescription, processing, evt, production, filetype, quality, runnb
        )
        if not retVal["OK"]:
            return retVal
        return S_OK([record[0] for record in retVal["Value"]])

    #############################################################################
    types_getAvailableTcks = [dict]

    def export_getAvailableTcks(self, in_dict):
        """more info in the BookkeepingClient.py."""
        return self.export_getTCKs(in_dict)

    #############################################################################
    types_getSteps = [int]

    @classmethod
    def export_getSteps(cls, prodID):
        """get list of steps used in a production"""
        return cls.bkkDB.getSteps(prodID)

    #############################################################################
    types_getStepsMetadata = [dict]

    @classmethod
    def export_getStepsMetadata(cls, in_dict):
        """It returns the step(s) which is produced  a given dataset."""
        cls.log.debug("getStepsMetadata", f"{in_dict}")
        configName = in_dict.get("ConfigName", default)
        configVersion = in_dict.get("ConfigVersion", default)
        cond = in_dict.get(
            "ConditionDescription",  # old single
            in_dict.get("SimulationConditions", in_dict.get("DataTakingConditions", default)),
        )
        procpass = in_dict.get("ProcessingPass", default)
        evt = in_dict.get("EventType", in_dict.get("EventTypeId", default))
        production = in_dict.get("Production", default)
        filetype = in_dict.get("FileType", default)
        runnb = in_dict.get("RunNumber", default)

        if "EventTypeId" in in_dict:
            cls.log.verbose("The EventTypeId has to be replaced by EventType!")

        if "Quality" in in_dict:
            cls.log.verbose("The Quality has to be replaced by DataQuality!")

        return cls.bkkDB.getStepsMetadata(configName, configVersion, cond, procpass, evt, production, filetype, runnb)

    #############################################################################
    types_getDirectoryMetadata_new = [list]

    @classmethod
    @deprecated("Use getDirectoryMetadata")
    def export_getDirectoryMetadata_new(cls, lfn):
        """more info in the BookkeepingClient.py."""
        return cls.bkkDB.getDirectoryMetadata(lfn)

        #############################################################################

    types_getDirectoryMetadata = [list]

    @classmethod
    def export_getDirectoryMetadata(cls, lfn):
        """more info in the BookkeepingClient.py."""
        cls.log.verbose("Getting the metadata for:", f"{lfn}")
        return cls.bkkDB.getDirectoryMetadata(lfn)

    #############################################################################
    types_getFilesForGUID = [str]

    @classmethod
    def export_getFilesForGUID(cls, guid):
        """It returns a file for a given GUID."""
        return cls.bkkDB.getFilesForGUID(guid)

    #############################################################################
    types_getRunsGroupedByDataTaking = []

    @classmethod
    def export_getRunsGroupedByDataTaking(cls):
        """It returns all the run numbers grouped by the data taking
        description."""
        return cls.bkkDB.getRunsGroupedByDataTaking()

    #############################################################################
    types_getListOfFills = [dict]

    @classmethod
    def export_getListOfFills(cls, in_dict):
        """It returns a list of FILL numbers for a given Configuration name,
        Configuration version and data taking description."""
        configName = in_dict.get("ConfigName", default)
        configVersion = in_dict.get("ConfigVersion", default)
        conddescription = in_dict.get(
            "ConditionDescription",  # old single
            in_dict.get("SimulationConditions", in_dict.get("DataTakingConditions", default)),
        )
        return cls.bkkDB.getListOfFills(configName, configVersion, conddescription)

    #############################################################################
    types_getRunsForFill = [int]

    @classmethod
    def export_getRunsForFill(cls, fillid):
        """It returns a list of runs for a given FILL."""
        return cls.bkkDB.getRunsForFill(fillid)

    #############################################################################
    types_getListOfRuns = [dict]

    @classmethod
    def export_getListOfRuns(cls, in_dict):
        """It returns a list of runs for a given conditions.

        Input parameter is a dictionary which has the following keys:
        'ConfigName', 'ConfigVersion', 'ConditionDescription',
        'EventType','ProcessingPass'
        """
        configName = in_dict.get("ConfigName", default)
        configVersion = in_dict.get("ConfigVersion", default)
        conddescription = in_dict.get(
            "ConditionDescription",  # old single
            in_dict.get("SimulationConditions", in_dict.get("DataTakingConditions", default)),
        )
        processing = in_dict.get("ProcessingPass", default)
        evt = in_dict.get("EventType", default)
        quality = in_dict.get("DataQuality", default)

        retVal = cls.bkkDB.getListOfRuns(configName, configVersion, conddescription, processing, evt, quality)
        if not retVal["OK"]:
            return retVal
        return S_OK([i[0] for i in retVal["Value"]])

    #############################################################################
    types_getListOfRunsInProd = [int]

    @classmethod
    def export_getListOfRunsInProd(cls, prod_id):
        """It returns a list of runs for a given production."""
        return cls.bkkDB.getListOfRunsInProd(prod_id)

    #############################################################################
    types_getInputOutputFilesForProd = [int, int]

    @classmethod
    def export_getInputOutputFilesForProd(cls, prod_id, run_number):
        """It returns a list of input and output files for a given production.

        The run number is used to filter the files as this results in faster queries.
        The list of available run numbers can be obtained using getListOfRunsInProd.
        """
        return cls.bkkDB.getInputOutputFilesForProd(prod_id, run_number)

    #################
    types_getOutputDescendantsForProd = [int, int]

    @classmethod
    def export_getOutputDescendantsForProd(cls, prod_id, run_number):
        """It returns the decendants of the output files for a given production.


        The run number is used to filter the files as this results in faster queries.
        The list of available run numbers can be obtained using getListOfRunsInProd.
        """
        return cls.bkkDB.getOutputDescendantsForProd(prod_id, run_number)

    #############################################################################
    types_getSimulationConditions = [dict]

    @classmethod
    def export_getSimulationConditions(cls, in_dict):
        """It returns a list of simulation conditions for a given conditions."""
        return cls.bkkDB.getSimulationConditions(in_dict)

    #############################################################################
    types_updateSimulationConditions = [dict]

    @classmethod
    def export_updateSimulationConditions(cls, in_dict):
        """It updates a given simulation condition."""
        return cls.bkkDB.updateSimulationConditions(in_dict)

    #############################################################################
    types_deleteSimulationConditions = [int]

    @classmethod
    def export_deleteSimulationConditions(cls, simid):
        """deletes a given simulation conditions."""
        return cls.bkkDB.deleteSimulationConditions(simid)

    #############################################################################
    types_getProductionSummaryFromView = [dict]

    @classmethod
    def export_getProductionSummaryFromView(cls, in_dict):
        """it returns a summary for a given condition."""
        return cls.bkkDB.getProductionSummaryFromView(in_dict)

    types_getJobInputOutputFiles = [list]

    @classmethod
    def export_getJobInputOutputFiles(cls, diracjobids):
        """It returns the input and output files for a given DIRAC jobid."""
        return cls.bkkDB.getJobInputOutputFiles(diracjobids)

    types_setRunOnlineFinished = [int]

    @classmethod
    def export_setRunOnlineFinished(cls, runnumber):
        """It is used to set the run finished..."""
        return cls.bkkDB.setRunStatusFinished(runnumber, "Y")

    types_setRunOnlineNotFinished = [int]

    @classmethod
    def export_setRunOnlineNotFinished(cls, runnumber):
        """You can set the runs not finished."""
        return cls.bkkDB.setRunStatusFinished(runnumber, "N")

    types_getRunStatus = [list]

    @classmethod
    def export_getRunStatus(cls, runnumbers):
        """it returns the status of the runs."""
        return cls.bkkDB.getRunStatus(runnumbers)

    types_bulkupdateFileMetaData = [dict]

    @classmethod
    def export_bulkupdateFileMetaData(cls, lfnswithmeta):
        """It updates the file metadata."""
        return cls.bkkDB.bulkupdateFileMetaData(lfnswithmeta)

    types_fixRunLuminosity = [list]

    @classmethod
    def export_fixRunLuminosity(cls, runnumbers):
        return cls.bkkDB.fixRunLuminosity(runnumbers)

    #############################################################################
    types_getProductionProducedEvents = [int]

    @classmethod
    def export_getProductionProducedEvents(cls, prodid):
        """it returns the number of events producced for a given production."""
        cls.log.debug("Retrieving the number of processed event for production", prodid)
        return cls.bkkDB.getProductionProducedEvents(prodid)

    #############################################################################
    types_bulkinsertEventType = [list]

    @classmethod
    def export_bulkinsertEventType(cls, eventtypes):
        """It inserts a list of event types to the db.

        :param eventtypes: it is a list of event types. For example, the list elements are the following

          .. code-block:: python

            {'EVTTYPEID': '12265021',
             'DESCRIPTION': 'Bu_D0pipipi,Kpi-withf2=DecProdCut_pCut1600MeV',
             'PRIMARY': '[B+ -> (D~0 -> K+ pi-) pi+ pi- pi+]cc'}


        :return: S_ERROR S_OK({'Failed':[],'Successful':[]})
        """
        return cls.bkkDB.bulkinsertEventType(eventtypes)

    #############################################################################
    types_bulkupdateEventType = [list]

    @classmethod
    def export_bulkupdateEventType(cls, eventtypes):
        """It updates a list of event types which are exist in the db.

        :param list eventtypes: it is a list of event types. For example: the list elements are the following:

          .. code-block:: python

          {'EVTTYPEID': '12265021',
          'DESCRIPTION': 'Bu_D0pipipi,Kpi-withf2=DecProdCut_pCut1600MeV',
          'PRIMARY': '[B+ -> (D~0 -> K+ pi-) pi+ pi- pi+]cc'}

        :return: S_ERROR S_OK({'Failed':[],'Successful':[]})
        """
        return cls.bkkDB.bulkupdateEventType(eventtypes)

    #############################################################################
    types_getRunConfigurationsAndDataTakingCondition = [int]

    @classmethod
    def export_getRunConfigurationsAndDataTakingCondition(cls, runnumber):
        """It returns minimal information for a given run.

        :param: int runnumber
        :return: S_OK()/S_ERROR ConfigName, ConfigVersion and DataTakingDescription
        """
        return cls.bkkDB.getRunConfigurationsAndDataTakingCondition(runnumber)

    types_deleteCertificationData = []

    @classmethod
    def export_deleteCertificationData(cls):
        """It destroy the data used by the integration test."""
        return cls.bkkDB.deleteCertificationData()

    types_updateProductionOutputfiles = []

    @classmethod
    def export_updateProductionOutputfiles(cls):
        """It is used to trigger an update of the productionoutputfiles table."""
        return cls.bkkDB.updateProductionOutputfiles()

    types_getAvailableTagsFromSteps = []

    @classmethod
    def export_getAvailableTagsFromSteps(cls):
        """It returns the all used datatbase tags: DDDB, CondDB, DQTag."""
        return cls.bkkDB.getAvailableTagsFromSteps()


class BookkeepingManagerHandler(BookkeepingManagerHandlerMixin, RequestHandler):
    pass
