import os
import sys


class BaseException(Exception):
    """
        BaseException class for all the others
        exceptions defined for this app.
    """
    def __init__(self, message, cause=None, *args, **kwargs):
        """
        BaseException gets a message and a cause. These params
        will be displayed when the program raises an exception that
        is a child of this class.

        :param message: obligatory
        :param cause: might be None
        """
        super(Exception, self).__init__()
        self.message = message
        self.cause = cause

        try:
            exc_type, exc_obj, exc_tb = sys.exc_info()
            self.filename = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
            self.fileline = exc_tb.tb_lineno
        except Exception, e:
            print args, kwargs
            self.filename = ""
            self.fileline = ""

    def __str__(self):
        """
        Override the str method for  all the exceptions.

        :return: str
        """
        # Get the exception class name
        exception_class_name = self.__class__.__name__

        # This is the str
        to_return = "%s: %s"%(exception_class_name, self.message)

        if self.cause:
            # Get the str of the cause
            to_return += "\r\nError at {filename}@{line}. Caused by: {cause}".format(
                filename=self.filename,
                line=self.fileline,
                cause=self.cause
            )

        return to_return

    def __repr__(self):
        """
        Override the __repr__ method for all the exceptions.

        :return: str
        """
        return str(self)
