#!/usr/bin/env python

#
# Base DM controller class.
#

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

import cherrypy
import httplib
import json

from sys import exc_info
from dm.common.utility.loggingManager import LoggingManager
from dm.common.constants import dmStatus
from dm.common.constants import dmHttpHeaders
from dm.common.exceptions.dmException import DmException
from dm.common.exceptions import dmExceptionMap
from dm.common.exceptions.internalError import InternalError

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

class DmController(object):
    """ Base controller class. """
    def __init__(self):
        self.logger = LoggingManager.getInstance().getLogger(self.__class__.__name__)

    @classmethod
    def getLogger(cls):
        logger = LoggingManager.getInstance().getLogger(cls.__name__)
        return logger

    @classmethod
    def addDmResponseHeaders(cls, status=dmStatus.DM_OK, msg='Success', exceptionType=None):
        cherrypy.response.headers[dmHttpHeaders.DM_STATUS_CODE_HTTP_HEADER] = status
        cherrypy.response.headers[dmHttpHeaders.DM_STATUS_MESSAGE_HTTP_HEADER] = msg
        if exceptionType is not None:
            cherrypy.response.headers[dmHttpHeaders.DM_EXCEPTION_TYPE_HTTP_HEADER] = exceptionType

    @classmethod
    def addDmSessionRoleHeaders(cls, role):
        cherrypy.response.headers[dmHttpHeaders.DM_SESSION_ROLE_HTTP_HEADER] = role

    @classmethod
    def addDmExceptionHeaders(cls, ex):
        cls.handleException(ex)

    @classmethod
    def handleCpException(cls):
        cherrypy.response.status = httplib.OK
        ex = exc_info()[1]
        if ex == None:
            ex = InternalError('Internal Webservice Error')
        cls.handleException(ex)

    @classmethod
    def handleException(cls, ex):
        exClass = ex.__class__.__name__.split('.')[-1]
        status = None
        msg = '%s' % ex
        msg = msg.split('\n')[0]
        for code in dmExceptionMap.DM_EXCEPTION_MAP.keys():
            exStr = dmExceptionMap.DM_EXCEPTION_MAP.get(code).split('.')[-1]
            if exStr == exClass:
                status = code
        if not status:
            status = dmStatus.DM_ERROR
        cls.addDmResponseHeaders(status, msg, exClass)

    @classmethod
    def formatJsonResponse(cls, response):
        cherrypy.response.headers['Content-Type'] = 'application/json'
        return '%s' % (response)

    @classmethod
    def toJson(cls, o):
        return json.dumps(o)

    @classmethod
    def fromJson(cls, s):
        return json.loads(s)

    @classmethod
    def listToJson(cls, dmObjectList):
        jsonList = []
        for dmObject in dmObjectList:
            jsonList.append(dmObject.getDictRep(keyList='ALL'))
        return json.dumps(jsonList)

    @classmethod
    def getSessionUser(cls):
        return cherrypy.serving.session.get('user')

    @classmethod
    def getSessionUsername(cls):
        return cherrypy.serving.session.get('_cp_username')

    # Exception decorator for all exposed method calls
    @classmethod
    def execute(cls, func):
        def decorate(*args, **kwargs):
            try:
                response = func(*args, **kwargs)
            except DmException, ex:
                cls.getLogger().error('%s' % ex)
                cls.handleException(ex)
                response = ex.getFullJsonRep()
            except Exception, ex:
                cls.getLogger().error('%s' % ex)
                cls.handleException(ex)
                response = InternalError(ex).getFullJsonRep()
            return cls.formatJsonResponse(response)
        return decorate