from pathlib import Path

from click import ClickException

from soopervisor._format import comma_separated


class BackendWithoutPresetsError(ClickException):
    """Raises when passing a preset to a backend doesn't have any"""

    def __init__(self, backend):
        super().__init__(
            f"Backend {str(backend)!r} does not have " "presets. Remove the argument."
        )


class InvalidPresetForBackendError(ClickException):
    """Raised if the passed preset is not valid for the passed backend"""

    def __init__(self, backend, preset, preset_values):
        super().__init__(
            f"Preset {preset!r} is not a valid value for "
            f"backend {str(backend)!r}. Valid presets are: "
            f"{comma_separated(preset_values)}"
        )


class ConfigurationError(ClickException):
    """
    Raised when there is a misconfiguration. Captured by the CLI to only
    show the error message and not the whole traceback
    """

    pass


class MissingDockerfileError(ClickException):
    """
    Raised when trying to build a Docker image but the DockerFile is missing
    """

    def __init__(self, env_name):
        self.env_name = env_name
        path = str(Path(env_name, "Dockerfile"))
        message = f"""\
Expected Dockerfile at {path!r} but it does not exist\
        """
        super().__init__(message)


class MissingConfigurationFileError(ClickException):
    """
    Raised if soopervisor.yaml is missing
    """

    def __init__(self):
        name = "soopervisor.yaml"
        super().__init__(
            f"Expected a {name!r} file in the current "
            "working directory, but such files does not exist"
        )


class ConfigurationFileTypeError(ClickException):
    """Raised if the configuration file does not have the right type"""

    def __init__(self, path, data):
        super().__init__(
            f"Expected {str(path)!r} to contain a dictionary "
            f"but got an object of type: {type(data).__name__}"
        )


class NotATaskError(ClickException):
    """
    Raised when a user passes an invalid task name
    """

    def __init__(self, task_name, dag):
        names = comma_separated(dag.keys())
        super().__init__(f"{task_name!r} is not a valit task name. Tasks are: {names}")


class UpToDateTaskError(ClickException):
    """Raised when a user tries to submit a task that is up-to-date"""

    def __init__(self, task_name):
        super().__init__(
            f"Task {task_name!r} is up-to-date, to force execution, "
            "pass: --mode force"
        )
