import abc
import os
import urllib.error
import urllib.parse
import urllib.request


class Solver(abc.ABC):
    @abc.abstractmethod
    def dump(self):
        pass

    @abc.abstractmethod
    def depsolve(self, arguments):
        pass

    @abc.abstractmethod
    def search(self, args):
        pass


class SolverBase(Solver):
    # put any shared helpers in here
    pass


class SolverException(Exception):
    pass


class GPGKeyReadError(SolverException):
    pass


class TransactionError(SolverException):
    pass


class RepoError(SolverException):
    pass


class NoReposError(SolverException):
    pass


class MarkingError(SolverException):
    pass


class DepsolveError(SolverException):
    pass


class InvalidRequestError(SolverException):
    pass


def modify_rootdir_path(path, root_dir):
    if path and root_dir:
        # if the root_dir is set, we need to translate the key path to be under this directory
        return os.path.join(root_dir, path.lstrip("/"))
    return path


def read_keys(paths, root_dir=None):
    keys = []
    for path in paths:
        url = urllib.parse.urlparse(path)
        if url.scheme == "file":
            path = url.path
            path = modify_rootdir_path(path, root_dir)
            try:
                with open(path, mode="r", encoding="utf-8") as keyfile:
                    keys.append(keyfile.read())
            except Exception as e:
                raise GPGKeyReadError(f"error loading gpg key from {path}: {e}") from e
        elif url.scheme in ["http", "https"]:
            try:
                resp = urllib.request.urlopen(urllib.request.Request(path))
                keys.append(resp.read().decode())
            except urllib.error.URLError as e:
                raise GPGKeyReadError(f"error reading remote gpg key at {path}: {e}") from e
        else:
            raise GPGKeyReadError(f"unknown url scheme for gpg key: {url.scheme} ({path})")
    return keys
