from __future__ import annotations

from .StiBaseResult import StiBaseResult
from ..enums.StiFrameworkType import StiFrameworkType
import codecs
import json
import typing

if typing.TYPE_CHECKING:
    from .StiBaseHandler import StiBaseHandler

class StiBaseResponse:
    """
    The result of executing an event handler request. 
    You can get the data, its type and other parameters necessary to create a web server response.
    """

    handler: StiBaseHandler = None
    result: StiBaseResult = None


### Private

    def __getArrtibutes(obj: object):
        return { attr: getattr(obj, attr) for attr in dir(obj) if not callable(getattr(obj, attr)) and not attr.startswith('_') }


### Properties

    @property
    def origin(self) -> str:
        """Returns the detected origin url for the handler response. Can be used for the 'Access-Control-Allow-Origin' header of the response."""

        return self.handler.origin

    @property
    def mimetype(self) -> str:
        """Returns the mime-type for the handler response."""

        return 'application/json'
    
    @property
    def contentType(self) -> str:
        """Returns the content type for the handler response. Can be used for the 'Content-Type' header of the response."""

        return self.mimetype + '; charset=utf-8'
    
    @property
    def data(self) -> bytes:
        """Returns the handler response as a byte array. When using encryption, the response will be encrypted and encoded into a Base64 string."""

        data = json.dumps(self.result, default = StiBaseResponse.__getArrtibutes)
        if self.handler.request.encryptData == True:
            data = codecs.encode(codecs.encode(data.encode(), 'base64').decode(), 'rot13')
        return data.encode()

### Public

    def getFrameworkResponse(self):
        """
        Returns a response intended for one of the supported frameworks specified in the arguments. 
        The supported frameworks are in the 'StiFrameworkType' enum. 
        If the framework is not specified, it will be determined based on the request.
        """
        
        if self.handler.framework == StiFrameworkType.DJANGO:
            try:
                from django.http import HttpResponse
                contentType = self.contentType
                response = HttpResponse(self.data, content_type = contentType)
                return response
            except:
                return self

        if self.handler.framework == StiFrameworkType.FLASK:
            try:
                from flask import make_response
                response = make_response(self.data)
                response.mimetype = self.mimetype
                response.headers.add('Access-Control-Allow-Origin', self.origin)
                return response
            except:
                return self
            
        if self.handler.framework == StiFrameworkType.TORNADO:
            try:
                return self.data
            except:
                return self

        return self
    

### Constructor

    def __init__(self, handler: StiBaseHandler, result: StiBaseResult = None):
        self.handler = handler
        self.result = result if result != None else self.handler.getResult()
