# -*- coding: utf8 -*-
'''
**********************************************
*       P R O T O C O L - C L A S S
*       for the biocase protocol
**********************************************
$RCSfile: biocase_protocol.py,v $
$Revision: 1260 $
$Author: j.holetschek $
$Date: 2013-02-07 11:38:43 +0100 (Do, 07. Feb 2013) $

Request and Response classes to support the biocase protocol.
'''

from biocase.wrapper.errorclasses import CouldNotPickleError, CMFError
import time, logging
from biocase.wrapper.cmf_base import CMFClass
from biocase.wrapper.dbmod.base_dbmod import DBBasemodule
from biocase.wrapper.protocol.base_protocol import ProtocolBaseClass
from biocase.wrapper.protocol.BioCASe.biocase_request  import RequestClass
from biocase.wrapper.protocol.BioCASe.biocase_response import ResponseClass
log = logging.getLogger("pywrapper.protocol.biocase")

class ProtocolClass(ProtocolBaseClass):
    '''The main protocol class accepting a standard API and managing requests and responses.'''
    NAME = "BioCASe"

    def __init__(self, dsaObj, diagnosticsHandler):
        log.info("BioCASe protocol used.")
        ProtocolBaseClass.__init__(self, dsaObj, diagnosticsHandler, RequestClass=RequestClass, ResponseClass=ResponseClass)

    def logProtocolSpecific(self):
        '''Return BioCASe specific logging info for both request and response'''
        logDetails = "[%s]" % self.requestObj.type
        if self.requestObj.count > 0:
            logDetails = "[count]"
        if self.requestObj.type in ["scan", "search"]:
            logDetails += " %i/%i" % (self.requestObj.start, self.requestObj.limit)
            try:
                logDetails += " q=%s" % unicode(self.requestObj.filter)
            except:
                log.exception("Cant log request filter!")
            if self.requestObj.type == "scan" and self.requestObj.scan is not None:
                    logDetails += " scan=%s" % self.requestObj.scan
        logDetails += " %s" % str(self.responseObj.recordStatus)
        return logDetails

    def processRequest(self):
        '''Starts to process the request and prepares output object.'''
        # capabilities

        if self.requestObj.type == "capabilities":
            log.debug("process capabilities request")
            self.responseObj.setCapabilitiesContent()
        # purely static CMFs
        elif self.requestObj.type == "static":
            log.debug("process static request")
            # create CMF object of the response-CMF for output of XML
            try:
                # build new CMF object
                CMFObject = CMFClass()
                CMFObject.loadCMFdata(self.psfObj.getCMFfilename(self.requestObj.resSchema), psfObj=self.psfObj)
            except CouldNotPickleError:
                pass
            except:
                raise CMFError(cmf=self.requestObj.resSchema)
            etree = CMFObject.createXMLResultET([[]])
            self.responseObj.setSearchContent(etree, self.resultStatus)
        # search or scan
        elif self.requestObj.type in ("search", "scan"):
            # chose DBmodule, connect to DB.
            from biocase.wrapper.operations import getOperationsObjectForDBMod
            operationObj = getOperationsObjectForDBMod(self.psfObj, self.responseObj)
            # remember dbmod in response object for protocol header generation later on
            self.dbmodVersion = DBBasemodule.__repr__(operationObj)
            # search or scan
            if self.requestObj.type == "scan":
                #scan
                log.debug("process scan request")
                scanList = operationObj.scan(self.requestObj)
                # copy list to response object
                self.responseObj.setScanContent(scanList)
            else:
                # SEARCH
                log.debug("process search request")
                # check if requested schemas are supported for output
                self.requestObj.areSchemasSupported()
                # check whether full result or hit-count is requested
                if self.requestObj.count:
                    # count hits (integer)
                    log.debug("do count")
                    x = operationObj.count(self.requestObj)
                    # copy count to the response object
                    self.responseObj.setCountContent(x)
                else:
                    t0 = time.time()
                    log.debug("do full search")
                    (self.resultET, self.resultStatus) = operationObj.search(self.requestObj)
                    log.debug("successful end of search request incl ET creation")
                    # copy result to the response object
                    if self.resultET is None:
                        log.warn("No result returned from search operation")
                    else:
                        self.responseObj.setSearchContent(self.resultET, self.resultStatus)
                    log.info("time to execute request is " + str(time.time() - t0))
        else:
            log.warn("Unknown Request-type : " + str(self.requestObj.type))
