import logging
import subprocess

import os

from . import finders, repo


logger = logging.getLogger(__name__)


class HookRunner(object):
    """
    Base class for running git hooks

    :var finder_class: The class to use to find the hooks to run.
    """
    finder_class = None

    def get_process_args(self, *args):
        """
        Gets the arguments pass to the hook.

        :param args: The original args to pas to the hook
        :return: The modified args to pass to the hook
        """
        return args

    def get_process_kwargs(self, **kwargs):
        """
        Gets the kwargs to pass to the hook

        :param kwargs: The original set of kwargs to pass to the hook
        :return: The modified kwargs to pass to the hook
        """
        return kwargs

    def get_finder_class(self):
        """
        Gets the class to use to find the hooks.

        :return: The class to use
        """
        return self.finder_class

    def get_finder(self):
        """
        Gets an instance of the finder class to use

        :return: The finder instance
        """
        return self.get_finder_class()()

    def run(self):
        """
        Runs all the registered commit hooks

        :return: A sum of the return codes generated by the registered hooks
        """
        finder = self.get_finder()
        logger.info(u'Running "{0}" hooks\n'.format(finder.hook_type))

        args = list(self.get_process_args())

        for k, v in sorted(self.get_process_kwargs().items()):
            if v:
                args.append(k)
                args.extend(v)

        res = 0
        for path in self.get_finder():
            logger.info(u'Running "{0}"'.format(os.path.basename(path)))
            res += subprocess.call([path] + args)

        return res


class PreCommitHookRunner(HookRunner):
    """
    Runs the 'pre-commit' hooks.
    """
    finder_class = finders.PreCommitHookFinder

    def get_process_args(self, *args):
        args += tuple(repo.added_files() + repo.modified_files())
        return super(PreCommitHookRunner, self).get_process_args(*args)

    def get_process_kwargs(self, **kwargs):
        kwargs.setdefault('--added-files', repo.added_files())
        kwargs.setdefault('--modified-files', repo.modified_files())
        kwargs.setdefault('--deleted-files', repo.deleted_files())
        return super(PreCommitHookRunner, self).get_process_kwargs(**kwargs)
