# Copyright 2019 Canonical Ltd.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
#     Unless required by applicable law or agreed to in writing, software
#     distributed under the License is distributed on an "AS IS" BASIS,
#     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#     See the License for the specific language governing permissions and
#     limitations under the License.


class JujuCharmNotFound(Exception):
    """The Charm can't be found or is not readable."""


class JujuControllerFailedConnecting(Exception):
    """Failed connecting to juju controller."""


class JujuModelAlreadyExists(Exception):
    """The model already exists."""


class JujuApplicationExists(Exception):
    """The Application already exists."""


class JujuApplicationNotFound(Exception):
    """The Application cannot be found."""


class JujuMachineNotFound(Exception):
    """The machine cannot be found."""


class JujuK8sProxycharmNotSupported(Exception):
    """K8s Proxy Charms not supported in this installation."""


class N2VCPrimitiveExecutionFailed(Exception):
    """Something failed while attempting to execute a primitive."""


class NetworkServiceDoesNotExist(Exception):
    """The Network Service being acted against does not exist."""


class PrimitiveDoesNotExist(Exception):
    """The Primitive being executed does not exist."""


class NoRouteToHost(Exception):
    """There was no route to the specified host."""


class AuthenticationFailed(Exception):
    """The authentication for the specified user failed."""


class MethodNotImplemented(Exception):
    """The method is not implemented."""


class N2VCException(Exception):
    """
    N2VC exception base class
    """

    def __init__(self, message: str = ""):
        Exception.__init__(self, message)
        self.message = message

    def __str__(self):
        return self.message

    def __repr__(self):
        return "{}({})".format(type(self), self.message)


class N2VCBadArgumentsException(N2VCException):
    """
    Bad argument values exception
    """

    def __init__(self, message: str = "", bad_args: list = None):
        N2VCException.__init__(self, message=message)
        self.bad_args = bad_args

    def __str__(self):
        return "<{}> Bad arguments: {} -> {}".format(
            type(self), super().__str__(), self.bad_args
        )


class N2VCConnectionException(N2VCException):
    """
    Error connecting to VCA
    """

    def __init__(self, message: str = "", url: str = None):
        N2VCException.__init__(self, message=message)
        self.url = url

    def __str__(self):
        return "<{}> Connection to {} failed: {}".format(
            type(self), self.url, super().__str__()
        )


class N2VCTimeoutException(N2VCException):
    """
    Timeout
    """

    def __init__(self, message: str = "", timeout: str = ""):
        N2VCException.__init__(self, message=message)
        self.timeout = timeout

    def __str__(self):
        return "<{}> {} timeout: {}".format(type(self), self.timeout, super().__str__())


class N2VCExecutionException(N2VCException):
    """
    Error executing primitive
    """

    def __init__(self, message: str = "", primitive_name: str = ""):
        N2VCException.__init__(self, message=message)
        self.primitive_name = primitive_name

    def __str__(self):
        return "<{}> Error executing primitive {} failed: {}".format(
            type(self), self.primitive_name, super().__str__()
        )


class N2VCInvalidCertificate(N2VCException):
    """
    Invalid certificate
    """

    def __init__(self, message: str = ""):
        N2VCException.__init__(self, message=message)

    def __str__(self):
        return "<{}> Invalid certificate: {}".format(type(self), super().__str__())


class N2VCNotFound(N2VCException):
    """
    Not found
    """

    def __init__(self, message: str = ""):
        N2VCException.__init__(self, message=message)

    def __str__(self):
        return "<{}> Not found: {}".format(type(self), super().__str__())


class K8sException(Exception):
    """
    K8s exception
    """

    def __init__(self, message: str):
        Exception.__init__(self, message)
        self._message = message

    def __str__(self):
        return self._message

    def __repr__(self):
        return self._message


class EntityInvalidException(Exception):
    """Entity is not valid, the type does not match any EntityType."""
