import os
import sys
import traceback
from dotty_dict import dotty
from jinja2 import Environment, FileSystemLoader

from .StackTrace import StackTrace


class Handler:
    def __init__(
        self,
    ):
        self.tabs = {}
        self.renderers = {
            # "javascript": JavascriptDebugRenderer,
        }
        self.extra = {}
        self.options = {}

    def set_options(self, options):
        self.options = dotty(options)
        return self

    def set_extra(self, **extra):
        self.extra = extra
        return self

    def add_renderer(self, name, renderer):
        self.renderers.update({name: renderer})
        return self

    def get_renderer(self, name):
        return self.renderers[name](self)

    def add_tab(self, tab_class):
        tab = tab_class(self)
        self.tabs.update({tab.name: tab})
        return self

    def get_tab(self, name):
        return self.tabs[name]

    def start(self, exception):
        """Start handling exception."""
        self._exception = exception
        self._type, self._value, self._original_traceback = (
            exc_type,
            exc_value,
            exc_traceback,
        ) = sys.exc_info()
        traceback_exc = traceback.TracebackException(
            self._type, self._value, self._original_traceback, capture_locals=True
        )
        self._stacktrace = StackTrace(
            traceback_exc, self._exception, offset=self.options.get("stack.offset")
        )
        self._stacktrace.generate()

        return self

    # helpers
    def exception(self):
        return self._exception.__class__.__name__

    def namespace(self):
        return self._exception.__class__.__module__ + "." + self.exception()

    def message(self):
        return str(self._exception)

    def stacktrace(self):
        return self._stacktrace

    def serialize(self):
        tabs = {}
        for name, tab in self.tabs.items():
            tabs[name] = tab.serialize()
        return {
            "config": self.options.to_dict(),
            "exception": {
                "absolute_path": os.getcwd(),
                "type": self.exception(),
                "message": self.message(),
                "namespace": self.namespace(),
                "stacktrace": self.stacktrace().serialize(),
            },
            "tabs": tabs,
        }

    def render(self):
        path = os.path.dirname(__file__)
        file_loader = FileSystemLoader(os.path.join(path, "templates/"))
        env = Environment(loader=file_loader)

        template = env.get_template("exception.html")
        data = self.serialize()
        print(data)
        return template.render({"data": data})
