import subprocess
import os
import pkgutil


class VersionController(object):
    def __init__(self, logger=None, package='mpunet'):
        from mpunet.logging.default_logger import ScreenLogger
        self.package_name = package
        self.package_loader = pkgutil.get_loader(package)
        self.logger = logger or ScreenLogger()
        self.git_path = os.path.split(os.path.split(self.package_loader.path)[0])[0]
        self._mem_path = None

    def log_version(self, logger=None):
        logger = logger or self.logger
        logger("{} version: {} ({}, {})".format(self.package_name,
                                                self.version,
                                                self.branch,
                                                self.current_commit))

    def __enter__(self):
        self._mem_path = os.getcwd()
        os.chdir(self.git_path)

    def __exit__(self, exc_type, exc_val, exc_tb):
        os.chdir(self._mem_path)
        self._mem_path = None

    def check_git(self):
        return bool(self.git_query("git status")) and \
               os.path.exists(self.git_path + "/.git")

    def git_query(self, string):
        with self:
            try:
                p = subprocess.Popen(string.split(),
                                     stdout=subprocess.PIPE,
                                     stderr=subprocess.PIPE)
                out, err = p.communicate()
            except FileNotFoundError:
                return None
            if not out:
                return None
            out = out.decode("utf-8").strip(" \n")
        return out

    @property
    def remote_url(self):
        return self.git_query("git config --get remote.origin.url")

    @property
    def version(self):
        module = self.package_loader.load_module()
        return module.__version__

    @property
    def current_commit(self):
        return self.git_query("git rev-parse --short HEAD")

    @property
    def latest_commit_in_branch(self, branch=None):
        branch = branch or self.branch
        url = self.remote_url
        commit = self.git_query("git ls-remote {} refs/heads/{}".format(
            url, branch
        ))
        if commit is None:
            raise OSError("Could not determine latest commit, did not find git.")
        return commit[:7]

    @property
    def branch(self):
        return self.git_query("git symbolic-ref --short HEAD")

    def set_commit(self, commit_id):
        self.git_query("git reset --hard {}".format(str(commit_id)[:7]))

    def set_branch(self, branch):
        self.git_query("git checkout {}".format(branch))

    def set_version(self, version):
        version = str(version).lower().strip(" v")
        self.set_branch("v{}".format(version))
        self.set_commit(self.latest_commit_in_branch)