"""
These system tests are testing the release of groovy+ catkin projects.
"""

from __future__ import print_function

import os
import sys

try:
    from vcstools.vcs_abstraction import get_vcs_client
except ImportError:
    print("vcstools was not detected, please install it.", file=sys.stderr)
    sys.exit(1)

from .common import create_release_repo

from ..utils.common import bloom_answer
from ..utils.common import change_directory
from ..utils.common import in_temporary_directory
from ..utils.common import user
from ..utils.package_version import change_upstream_version

from bloom.git import branch_exists
from bloom.git import inbranch

from bloom.util import code

from bloom.commands.git.patch import export_cmd
from bloom.commands.git.patch import import_cmd
from bloom.commands.git.patch import remove_cmd

from bloom.generators.debian.generator import sanitize_package_name


def create_upstream_repository(packages, directory=None):
    upstream_dir = 'upstream_repo_groovy'
    user('mkdir ' + upstream_dir)
    with change_directory(upstream_dir):
        user('git init .')
        user('echo "readme stuff" >> README.md')
        user('git add README.md')
        user('git commit -m "Initial commit" --allow-empty')
        user('git checkout -b groovy_devel')
        for package in packages:
            user('mkdir ' + package)
            with change_directory(package if len(packages) != 1 else '.'):
                package_xml = """\
<?xml version="1.0"?>
<package>
  <name>{0}</name>
  <version>0.1.0</version>
  <description>A catkin (groovy) ROS package called '{0}'</description>
  <maintainer email="bar@baz.com">Bar</maintainer>
  <license>BSD</license>

  <url type="bugtracker">https://github.com/ros/this/issues</url>
  <url type="repository">https://github.com/ros/this</url>

  <build_depend>catkin</build_depend>

  <run_depend>catkin</run_depend>
  <!-- required for messages generated by gencpp -->
  <run_depend>roscpp_core</run_depend>
</package>
""".format(package)
                with open('package.xml', 'w+') as f:
                    f.write(package_xml)
                user('touch .cproject')
                user('touch .project')
                user('mkdir -p include/sym')
                user('touch include/{0}.h'.format(package))
                os.symlink('../{0}.h'.format(package), 'include/sym/{0}.h'.format(package))
                user('git add package.xml .cproject .project include')
        user('git commit -m "Releasing version 0.1.0" --allow-empty')
        user('git tag 0.1.0 -m "Releasing version 0.1.0"')
        return os.getcwd()


def _test_unary_package_repository(release_dir, version, directory=None):
    print("Testing in {0} at version {1}".format(release_dir, version))
    with change_directory(release_dir):
        # First run everything
        with bloom_answer(bloom_answer.ASSERT_NO_QUESTION):
            cmd = 'git-bloom-release{0} groovy'
            if 'BLOOM_VERBOSE' not in os.environ:
                cmd = cmd.format(' --quiet')
            else:
                cmd = cmd.format('')
            user(cmd, silent=False)
        ###
        ### Import upstream
        ###
        # does the upstream branch exist?
        assert branch_exists('upstream', local_only=True), "no upstream branch"
        # does the upstrea/<version> tag exist?
        ret, out, err = user('git tag', return_io=True)
        assert out.count('upstream/' + version) == 1, "no upstream tag created"
        # Is the package.xml from upstream in the upstream branch now?
        with inbranch('upstream'):
            assert os.path.exists('package.xml'), \
                "upstream did not import: '" + os.getcwd() + "': " + \
                str(os.listdir(os.getcwd()))
            with open('package.xml') as f:
                package_xml = f.read()
                assert package_xml.count(version), "not right file"

        ###
        ### Release generator
        ###
        # patch import should have reported OK
        assert ret == code.OK, "actually returned ({0})".format(ret)
        # do the proper branches exist?
        assert branch_exists('release/groovy/foo'), \
            "no release/groovy/foo branch"
        assert branch_exists('patches/release/groovy/foo'), \
            "no patches/release/groovy/foo branch"
        # was the release tag created?
        ret, out, err = user('git tag', return_io=True)
        expected = 'release/groovy/foo/' + version + '-0'
        assert out.count(expected) == 1, \
            "no release tag created, expected: '{0}'".format(expected)

        ###
        ### Make patch
        ###
        with inbranch('release/groovy/foo'):
            assert os.path.islink('include/sym/foo.h'), "Symbolic link lost during pipeline"
            if os.path.exists('include/foo.h'):
                user('git rm include/foo.h')
            else:
                if not os.path.exists('include'):
                    os.makedirs('include')
                user('touch include/foo.h')
                user('git add include/foo.h')
            user('git commit -m "A release patch" --allow-empty')

        ###
        ### Test import and export
        ###
        with inbranch('release/groovy/foo'):
            export_cmd.export_patches()
            remove_cmd.remove_patches()
            import_cmd.import_patches()

        ###
        ### Release generator, again
        ###
        # patch import should have reported OK
        assert ret == code.OK, "actually returned ({0})".format(ret)
        # do the proper branches exist?
        assert branch_exists('release/groovy/foo'), \
            "no release/groovy/foo branch"
        assert branch_exists('patches/release/groovy/foo'), \
            "no patches/release/groovy/foo branch"
        # was the release tag created?
        ret, out, err = user('git tag', return_io=True)
        assert out.count('release/groovy/foo/' + version) == 1, \
            "no release tag created"


@in_temporary_directory
def test_unary_package_repository(directory=None):
    """
    Release a single package catkin (groovy) repository.
    """
    directory = directory if directory is not None else os.getcwd()
    # Setup
    upstream_dir = create_upstream_repository(['foo'], directory)
    upstream_url = 'file://' + upstream_dir
    release_url = create_release_repo(