#!/usr/bin/env python
"""CaptainHook

Usage:
  captainhook install [--use-virtualenv-python]
  captainhook run
  captainhook -h | --help
  captainhook --version

Options:
  -h --help                    Show this screen.
  --version                    Show version.
  --use-virtualenv-python      Use the current virtualenv when running hook
                               scripts. [Default: false].
"""
import os
import os.path
from os.path import join, exists
import sys

import captainhook

package_location = os.path.dirname(captainhook.__file__)


def get_git_location(folder):
    if '.git' in os.listdir(folder):
        return os.path.join(folder, '.git')
    elif folder == '/':
        return False
    else:
        return get_git_location(os.path.dirname(folder))


def is_captain_hook_script(filepath):
    "Check to see if the given filepath is a captain hook owned script"
    with open(filepath, 'r') as script:
        if "CAPTAINHOOK IDENTIFIER" in script.read():
            return True
    return False


def add_version_number_to_file(version, filepath):
    """Add the version number given to the module at the given path"""
    with open(filepath, 'r') as f:
        content = f.readlines()

    with open(filepath, 'w') as f:
        f.write('__version__ = "{0}"\n'.format(version))
        f.writelines(content)


def install_checkers(git_location):
    """
    Install checkers package into the git hooks folder.

    Only override existing checkers if they are owned by captainhook.
    """
    dest_checker_folder = join(git_location, 'hooks', 'checkers')
    if not exists(dest_checker_folder):
        os.mkdir(dest_checker_folder)

    # Remove all captain hook scripts so that we can be sure
    # any renames of captainhook scripts are OK.
    for filename in os.listdir(dest_checker_folder):
        destination = join(dest_checker_folder, filename)
        if is_captain_hook_script(destination):
            os.remove(destination)

    source_checker_folder = join(package_location, 'checkers')

    for filename in os.listdir(source_checker_folder):
        if not filename.endswith('.py'):
            continue
        source = join(source_checker_folder, filename)
        destination = join(dest_checker_folder, filename)

        if exists(destination) and not is_captain_hook_script(destination):
            print(
                'Not installing checker {0}. One already exists unowned '
                'by captainhook.'.format(filename)
            )
            continue
        print("Installing check: {0}".format(filename))
        os.system("cp {0} {1}".format(source, destination))

    checker_constructor = join(dest_checker_folder, '__init__.py')
    add_version_number_to_file(captainhook.__version__, checker_constructor)


def install_pre_commit_hook(git_location, use_virtualenv=False):
    """
    Install the pre commit hook.

    Check that there is not pre-commit hook already installed that is not owned
    by captain hook.
    """
    print("Installing pre_commit.py to {0}".format(git_location))
    pre_commit_path = join(package_location, 'pre_commit.py')
    pre_commit_destination = join(git_location, 'hooks', 'pre-commit')
    if exists(pre_commit_destination):
        if is_captain_hook_script(pre_commit_destination):
            print("Overriding existing captainhook script at {0}".format(
                pre_commit_destination))
        else:
            print("There is already something at {0}. "
                  "Move it and try again.".format(pre_commit_destination))
            return
    os.system("cp {0} {1}".format(pre_commit_path, pre_commit_destination))
    os.system('chmod +x {0}'.format(pre_commit_destination))
    if use_virtualenv:
        print("Configuring pre-commit hook to use virtualenv")
        cmd = 'sed -i '' "1 s,^.*$,#!{}," {}'.format(sys.executable,
                                                     pre_commit_destination)
        os.system(cmd)


def get_repo_version(git_location):
    "Get the git-installed version of captainhook"
    checker_constructor = join(
        git_location, 'hooks', 'checkers', '__init__.py')
    if not os.path.exists(checker_constructor):
        return 'Not installed'
    sys.path.append(join(git_location, 'hooks'))
    import checkers
    version = getattr(checkers, '__version__', '< 0.8.2')
    sys.path.pop()
    return version


if __name__ == '__main__':
    import docopt
    arguments = docopt.docopt(__doc__)
    git_location = get_git_location(os.getcwd())
    if not git_location:
        print("You need to be in a git repo to run captainhook.")
        sys.exit(1)

    if arguments['--version']:
        print("Environment version: {}".format(captainhook.__version__))
        if git_location:
            repo_version = get_repo_version(git_location)
            print("Git repo version: {}".format(repo_version))
        sys.exit(0)

    if arguments['install']:
        print("Installing {0}".format(captainhook.VERSION))
        install_pre_commit_hook(git_location,
                                arguments['--use-virtualenv-python'])
        install_checkers(git_location)
    elif arguments['run']:
        pre_commit_script = join(git_location, 'hooks', 'pre-commit')
        if not exists(pre_commit_script):
            print('Try installing the hook script first: captainhook install')
            sys.exit(1)
        # Perform a run of the hook, ignoring what's not committed.
        os.system(pre_commit_script + ' --all')
