def manage_exception(status_code, response=None):
    """
    Given the returned status code, this function will raise the relevant exception
    This function does not handle 200 responses, it just returns None
    :param status_code:
    :param response:
    :return:
    """

    if response is None:
        response = EmptyResponse(status_code=status_code)

    if status_code == 400:
        raise AppBadRequest(response=response)

    if status_code == 401:
        raise AppUnauthorized(response=response)

    if status_code == 403:
        raise AppForbidden(response=response)

    if status_code == 404:
        raise AppNotFound(response=response)

    if status_code == 409:
        raise AppConflict(response=response)

    if status_code == 415:
        raise AppUnsupportedMediaType(response=response)

    if status_code == 500:
        raise AppInternalError(response=response)


class EmptyResponse:
    def __init__(self, status_code):
        self.status_code = status_code
        self.text = "Generic Error"


class AppException(Exception):
    def __init__(self, response, msg=None):
        self.response = response
        self.status_code = response.status_code
        super().__init__(msg)


class AppBadRequest(AppException):
    # HTTP 400: Bad Request
    def __init__(self, response):
        super().__init__(response, response.text)


class AppUnauthorized(AppException):
    # HTTP 401: Unauthorized
    def __init__(self, response):
        super().__init__(response, response.text)


class AppForbidden(AppException):
    # HTTP 403: Forbidden
    def __init__(self, response):
        super().__init__(response, response.text)


class AppNotFound(AppException):
    # HTTP 404: Not Found
    def __init__(self, response):
        super().__init__(response, response.text)


class AppConflict(AppException):
    # HTTP 409: Conflict
    def __init__(self, response):
        super().__init__(response, response.text)


class AppUnsupportedMediaType(AppException):
    # HTTP 415: UnsupportedMediaType
    def __init__(self, response):
        super().__init__(response, response.text)


class AppInternalError(AppException):
    # HTTP 500: Internal Error
    def __init__(self, response):
        super().__init__(response, response.text)


class AppNotImplemented(AppException):
    # HTTP 501
    def __init__(self, response):
        super().__init__(response, response.text)


class AppExceptionUnknown(AppException):
    # HTTP Unknown
    def __init__(self, response):
        super().__init__(response, response.text)


class AppNotAuthenticated(AppException):
    # Not Authenticated
    def __init__(self):
        super().__init__(None, "Not Authenticated")
