#!/usr/bin/env python3
# pylint: disable=invalid-name
"""Backup a Git repositories namespace to my GitLab instance.

Which means creating a namespace in GitLab, creating a project for every
repository in the namespace, adding a remote to the repository and pushing
everything to that project.

In this context, a namespace is a directory under ~/Repositories.
"""

import argparse
import pathlib
import sys
import os
import os.path
import sh  # pylint: disable=import-error
from sh.contrib import git  # pylint: disable=import-error

sys.path.append(os.path.expanduser("~/Documents/bin"))

import rcfiles.git  # noqa: E402 pylint: disable=wrong-import-position
import rcfiles.gitlab  # noqa: E402 pylint: disable=wrong-import-position


def namespace_path(namespace):
    """Returns the full path to the namespace.

    Raises an exception if the path doesn't exits or isn't a directory.
    """
    path = pathlib.Path(os.path.expanduser("~/Repositories/" + namespace))
    if not path.exists():
        raise argparse.ArgumentTypeError("Path {} does not exit.".format(path))
    if not path.is_dir():
        raise argparse.ArgumentTypeError(
            "Path {} is not a directory.".format(path)
        )
    return path


def list_repositories(namespace):
    """Returns a list of paths under the namespace that are Git
    repositories."""
    return [x for x in namespace.iterdir() if rcfiles.git.is_repo(x)]


if __name__ == "__main__":
    parser = argparse.ArgumentParser(description=__doc__)
    parser.add_argument("namespace", type=namespace_path)
    args = parser.parse_args()

    with rcfiles.gitlab.connect() as conn:
        group = rcfiles.gitlab.get_group(conn, args.namespace.name)
        if group is None:
            group = rcfiles.gitlab.create_group(
                conn, args.namespace.name, visibility="internal"
            )
            print(
                "Created new group id: {}, name: {}, path: {}.".format(
                    group.id, group.name, group.path
                ),
                file=sys.stderr,
            )
        else:
            print(
                "Using existing group id: {}, name: {}, path: {}.".format(
                    group.id, group.name, group.path
                ),
                file=sys.stderr,
            )
        for repo in list_repositories(args.namespace):
            project = rcfiles.gitlab.get_project(conn, group.name, repo.name)
            if project is None:
                project = rcfiles.gitlab.create_project(
                    conn, repo.name, group.name
                )
                print(
                    "Created new project id: {}, name: {}, path: {}.".format(
                        project.id, project.name, project.path
                    ),
                    file=sys.stderr,
                )
            else:
                print(
                    "Using existing project id: {}, name: {}, path: {}.".format(  # noqa: E501
                        project.id, project.name, project.path
                    ),
                    file=sys.stderr,
                )
            with sh.pushd(repo):
                if "shore.co.il" in git.remote().splitlines():
                    print(
                        "Setting the remote URL in {}.".format(repo.name),
                        file=sys.stderr,
                    )
                    git.remote(
                        "set-url", "shore.co.il", project.ssh_url_to_repo
                    )
                else:
                    print(
                        "Adding remote in {}.".format(repo.name),
                        file=sys.stderr,
                    )
                    git.remote("add", "shore.co.il", project.ssh_url_to_repo)
                print(
                    "Pushing to {}.".format(project.ssh_url_to_repo),
                    file=sys.stderr,
                )
                git.push("--all", "shore.co.il")
