#
# -*- coding: utf-8 -*-

'''General things all querytool scripts need.
It also adjusts the sys path via biocase.adjustpath.py .
This module should be executed via execfile('ABS PATH TO HERE'). 
'''

############################################################################################################
#
#   IMPORTS
#
#===========================================================================================================

import cgitb; cgitb.enable()
import cgi
import os, sys, string
from types import *
import urllib, logging, biocase.initlogs
biocase.initlogs.initWebappLogging()

import biocase.configuration
from biocase import __version__
from biocase.querytool.preferences import getPreferences, QTPreferences
from biocase.tools.htmltools  import ankerClass, escapeHtml, escapeBackslash, getDropDownHtml, getDropDownOptionHtml
from biocase.tools.templating import PageMacro, genOptionList
from biocase.datasources import getDsaList
from biocase.tools.various_functions import unique
from biocase.querytool.filter import *
from biocase.querytool.querydispatcher import QueryDispatcher, WrapperError
from biocase.querytool.querygenerator import QueryGenerator


############################################################################################################
#
#   GENERAL FUNCTIONS
#
#===========================================================================================================
    
def createFilter(form, schemaObj, LOPClass=AndClass):
    class paraClass:
        '''simple class to handle parameters'''
        def __init__(self):
            self.conceptObj = None
            self.value = None
            self.copType = '~'
    # build filter object
    filterObj = LOPClass()
    # first check if their is a filterstring
    if form.has_key('filter'):
        oldFilter = createFilterObjFromString( form.getUnicodeValues('filter'), schemaObj)
        log.info("OLD FILTER FROM STRING '%s' BECOMES '%s'"%(form.getUnicodeValues('filter'), unicode(oldFilter)))
        log.debug("  AS XML: %s"%(oldFilter._reprXML()))
        filterObj.addOperand(oldFilter)
        
    else:
        log.info('NO OLD FILTER FOUND'        )
    # then check for additional operands
    args = {}
    for para in form.keys():
        # make underscores spaces again as in the prefs object
        if para[:3]=='con':
            label=para[3:]
            if args.has_key(label):
                # the parameter tuple already exists
                args[label].conceptObj = schemaObj.getConcept(label)
                args[label].value = form.getUnicodeValues(para)
            else:
                # create new para object
                pObj = paraClass()
                pObj.conceptObj = schemaObj.getConcept(label)
                pObj.value = form.getUnicodeValues(para)
                args[label] = pObj
        if para[:3]=='cop':
            label=para[3:]
            if args.has_key(label):
                # the parameter tuple already exists
                args[label].copType = form.getUnicodeValues(para)
            else:
                pObj = paraClass()
                pObj.copType = form.getUnicodeValues(para)
                args[label] = pObj
    log.info("FILTER ARGS: %s"%unicode(args))
    # remove empty args (Value=None)
    for label, arg in args.items():
        if arg.value is None or len(arg.value)==0:
            del args[label]
    log.debug("FILTER ARGS CLEANED: %s"%unicode(args))
    # create new COP operands
    copclasses = {'~':LikeClass,'=':EqualsClass,'<':LesserClass,'>':GreaterClass}
    for label, pObj in args.items():
        copObj = binaryCopObjectFactory(CopClass=copclasses[ pObj.copType ], conceptObj=pObj.conceptObj, val=pObj.value)
        log.debug(copObj)
        #log.debug(" COP CREATED: %s"%copObj)
        filterObj.addOperand( copObj )
    return getOptimizedFilterObj(filterObj)

def logDiagnostics(diagnosticsList):
    log.debug("WRAPPER DIAGNOSTICS:")
    for d in diagnosticsList:
        log.debug(d[2])    
    
def printOverHTTP(templ):
    print 'Content-Type: text/html; charset=utf-8\n\n'
    try:
        print str(templ)
    except:
        log.error("Couldnt print template.")



class FieldStorageForUnicode(cgi.FieldStorage):
    '''Transforms fieldstorage data into unicode with the given encoding when creating the object.'''
    ENCODING = 'utf-8'
    def __init__(self, encoding='utf-8'):
        self.__class__.ENCODING = encoding
        cgi.FieldStorage.__init__(self)
        self.QS = cgi.parse_qs( os.environ.get("QUERY_STRING","") )
        
    def has_key(self, key):
        '''Subclass method to also find raw querystring parameters.'''
        if cgi.FieldStorage.has_key(self, key):
            return True
        elif self.QS.has_key(key):
            return True
        else:
            return False
    
    def getvalue(self, key):
        '''Subclass method to also find raw querystring parameters.'''
        if cgi.FieldStorage.has_key(self, key):
            return cgi.FieldStorage.getvalue(self, key)
        else:
            return self.QS[key][0]
            
    def getUnicodeValues(self, para):
        # return a list of form values in unicode
        #return unicode( self.getvalue(para, None) , self.__class__.ENCODING)
        if self.has_key(para):
            if type(self.getvalue(para)) in (ListType,TupleType):
                return [unicode( val, self.__class__.ENCODING) for val in self.getvalue(para)]
            else:
                return unicode( self.getvalue(para), self.__class__.ENCODING)
        else:
            return None

############################################################################################################
#
#   MAIN
#
#===========================================================================================================


# get global project configurations
cfg = biocase.configuration.Cfg()
# debugging to file
log = logging.getLogger("webapp.querytool")
log.info("--- NEW QUERYTOOL REQUEST ---")

# dirs used with the querytool
configDir        = os.path.join(cfg.configurationLocator, 'querytool') # querytool config dir


#
# ANALYZE CGI ENVIRONMENT
#
form = FieldStorageForUnicode()

# check datasource alias (DSA) to parse preferences etc.
if form.has_key('dsa'):
    dsa = form.getUnicodeValues('dsa')
    wrapper_url = cfg.getAccessPoint(dsa)
    prefs = getPreferences(dsa, cfg)
else:
    dsa = None
    wrapper_url = None
    prefs = QTPreferences()
    # check for skin to use:
    if form.has_key('skin'):
        prefs.skin = form.getUnicodeValues('skin')

# allow overriding of wrapper url
if form.has_key('wrapper_url'):
    wrapper_url = form.getUnicodeValues('wrapper_url')

# default directory for HTML templates
skinDir = os.path.join(configDir, 'skins', 'default') 
# use custom skin?
if prefs.skin is not None:
    fn = os.path.join(configDir, 'skins', prefs.skin)
    if os.path.isdir(fn):
        skinDir = fn
    else:
        log.warn("Cannot find skin %s" % prefs.skin)
        
log.debug(str(prefs))
# which schema to use?
if form.has_key('schema'):
    schemaObj = prefs.getSchema( form.getUnicodeValues('schema') )
    if schemaObj is None:
        raise "The requested schema %s is not supported by this datasource." % form.getvalue('schema')
else:
    schemaObj = prefs.defaultSchema
schema = None
if schemaObj is not None:
    schema = schemaObj.NS


# was there a security role passed?
if form.has_key('role'):
    security_role = form.getUnicodeValues('role')
else:
    security_role = None

# for debugging:
log.info( "WRAPPER URL: %s" %(unicode(wrapper_url)))
log.info("DSA: %s" %(unicode(dsa)))
log.info("SECURITY ROLE: %s" % (security_role))
log.info("SCHEMA: %s" %(unicode(schema)))
log.info("SKIN: %s" %(unicode(prefs.skin)))
log.debug("SkinDir: %s" %(unicode(skinDir)))
log.debug(unicode(prefs))

    
