# -*- coding: utf-8  -*-
#
# Copyright (C) 2011-2018 Ben Kurtovic <ben.kurtovic@gmail.com>
# Released under the terms of the MIT License. See LICENSE for details.

from __future__ import print_function

import argparse
import os
import platform
import sys

from colorama import init as color_init, Style

from gitup import __version__
from gitup.config import (get_default_config_path, get_bookmarks, add_bookmarks,
                          delete_bookmarks, list_bookmarks, clean_bookmarks)
from gitup.update import update_bookmarks, update_directories, run_command

def _decode(path):
    """Decode the given string using the system's filesystem encoding."""
    if sys.version_info.major > 2:
        return path
    return path.decode(sys.getfilesystemencoding())

def _build_parser():
    """Build and return the argument parser."""
    parser = argparse.ArgumentParser(
        description="Easily update multiple git repositories at once.",
        epilog="""
            Both relative and absolute paths are accepted by all arguments.
            Direct bug reports and feature requests to
            https://github.com/earwig/git-repo-updater.""",
        add_help=False)

    group_u = parser.add_argument_group("updating repositories")
    group_b = parser.add_argument_group("bookmarking")
    group_a = parser.add_argument_group("advanced")
    group_m = parser.add_argument_group("miscellaneous")

    group_u.add_argument(
        'directories_to_update', nargs="*", metavar="path", type=_decode,
        help="""update this repository, or all repositories it contains
        (if not a repo directly)""")
    group_u.add_argument(
        '-u', '--update', action="store_true", help="""update all bookmarks
        (default behavior when called without arguments)""")
    group_u.add_argument(
        '-t', '--depth', dest="max_depth", metavar="n", type=int, default=3,
        help="""max recursion depth when searching for repos in subdirectories
        (default: 3; use 0 for no recursion, or -1 for unlimited)""")
    group_u.add_argument(
        '-c', '--current-only', action="store_true", help="""only fetch the
        remote tracked by the current branch instead of all remotes""")
    group_u.add_argument(
        '-f', '--fetch-only', action="store_true",
        help="only fetch remotes, don't try to fast-forward any branches")
    group_u.add_argument(
        '-p', '--prune', action="store_true", help="""after fetching, delete
        remote-tracking branches that no longer exist on their remote""")

    group_b.add_argument(
        '-a', '--add', dest="bookmarks_to_add", nargs="+", metavar="path",
        type=_decode, help="add directory(s) as bookmarks")
    group_b.add_argument(
        '-d', '--delete', dest="bookmarks_to_del", nargs="+", metavar="path",
        type=_decode,
        help="delete bookmark(s) (leaves actual directories alone)")
    group_b.add_argument(
        '-l', '--list', dest="list_bookmarks", action="store_true",
        help="list current bookmarks")
    group_b.add_argument(
        '-n', '--clean', '--cleanup', dest="clean_bookmarks",
        action="store_true", help="delete any bookmarks that don't exist")
    group_b.add_argument(
        '-b', '--bookmark-file', nargs="?", metavar="path", type=_decode,
        help="use a specific bookmark config file (default: {0})".format(
            get_default_config_path()))

    group_a.add_argument(
        '-e', '--exec', '--batch', dest="command", metavar="command",
        help="run a shell command on all repos")

    group_m.add_argument(
        '-h', '--help', action="help", help="show this help message and exit")
    group_m.add_argument(
        '-v', '--version', action="version",
        version="gitup {0} (Python {1})".format(
            __version__, platform.python_version()))
    group_m.add_argument(
        '--selftest', action="store_true",
        help="run integrated test suite and exit (pytest must be available)")

    return parser

def _selftest():
    """Run the integrated test suite with pytest."""
    from .test import run_tests
    run_tests()

def main():
    """Parse arguments and then call the appropriate function(s)."""
    parser = _build_parser()
    color_init(autoreset=True)
    args = parser.parse_args()

    print(Style.BRIGHT + "gitup" + Style.RESET_ALL + ": the git-repo-updater")
    print()

    if args.selftest:
        _selftest()
        return

    if args.bookmark_file:
        args.bookmark_file = os.path.expanduser(args.bookmark_file)

    acted = False
    if args.bookmarks_to_add:
        add_bookmarks(args.bookmarks_to_add, args.bookmark_file)
        acted = True
    if args.bookmarks_to_del:
        delete_bookmarks(args.bookmarks_to_del, args.bookmark_file)
        acted = True
    if args.list_bookmarks:
        list_bookmarks(args.bookmark_file)
        acted = True
    if args.clean_bookmarks:
        clean_bookmarks(args.bookmark_file)
        acted = True

    if args.command:
        if args.directories_to_update:
            run_command(args.directories_to_update, args)
        if args.update or not args.directories_to_update:
            run_command(get_bookmarks(args.bookmark_file), args)
    else:
        if args.directories_to_update:
            update_directories(args.directories_to_update, args)
            acted = True
        if args.update or not acted:
            update_bookmarks(get_bookmarks(args.bookmark_file), args)

def run():
    """Thin wrapper for main() that catches KeyboardInterrupts."""
    try:
        main()
    except KeyboardInterrupt:
        print("Stopped by user.")
