import subprocess as sp
import tempfile
import tarfile
import os
import shlex
import logging

from . import utils

from conda_build.metadata import MetaData

logger = logging.getLogger(__name__)


def get_tests(path):
    "Extract tests from a built package"
    tmp = tempfile.mkdtemp()
    t = tarfile.open(path)
    t.extractall(tmp)
    input_dir = os.path.join(tmp, 'info', 'recipe')

    tests = []
    recipe_meta = MetaData(input_dir)

    tests_commands = recipe_meta.get_value('test/commands')
    tests_imports = recipe_meta.get_value('test/imports')
    requirements = recipe_meta.get_value('requirements/run')

    if tests_imports or tests_commands:
        if tests_commands:
            tests.append(' && '.join(tests_commands))
        if tests_imports and 'python' in requirements:
            tests.append(
                ' && '.join('python -c "import %s"' % imp
                            for imp in tests_imports)
            )
        elif tests_imports and (
            'perl' in requirements or 'perl-threaded' in requirements
        ):
            tests.append(
                ' && '.join('''perl -e "use %s;"''' % imp
                            for imp in tests_imports)
            )

    tests = ' && '.join(tests)
    tests = tests.replace('$R ', 'Rscript ')
    return tests


def test_package(path, name_override='tmp', channels=None, mulled_args=""):
    """
    Tests a built package in a minimal docker container.

    Parameters
    ----------
    path : str
        Path to a .tar.bz2 package built by conda-build

    name_override : str
        Passed as the --name-override argument to mulled-build

    channels : None | str | list
        The local channel of the provided package will be added automatically;
        `channels` are channels to use in addition to the local channel.

    mulled_args : str
        Mechanism for passing arguments to the mulled-build command. They will
        be split with shlex.split and passed to the mulled-build command. E.g.,
        mulled_args="--dry-run --involucro-path /opt/involucro"

    """

    assert path.endswith('.tar.bz2'), "Unrecognized path {0}".format(path)
    # assert os.path.exists(path), '{0} does not exist'.format(path)

    conda_bld_dir = os.path.abspath(os.path.dirname(os.path.dirname(path)))

    sp.check_call(['conda', 'index', os.path.dirname(path)])

    pkg = os.path.basename(path).replace('.tar.bz2', '')
    toks = pkg.split('-')
    build_string = toks[-1]
    version = toks[-2]
    name = '-'.join(toks[:-2])

    spec = '='.join([name, version, build_string])

    extra_channels = ['file:/{0}'.format(conda_bld_dir)]
    if channels is None:
        channels = []
    if isinstance(channels, str):
        channels = [channels]
    extra_channels.extend(channels)
    channel_args = ['--extra-channels',','.join(extra_channels)]

    tests = get_tests(path)
    logger.debug('Tests to run: %s', tests)

    cmds = [
        'mulled-build',
        'build-and-test',
        spec,
        '--name-override', name_override,
        '--test', tests
    ]
    cmds += channel_args
    cmds += shlex.split(mulled_args)
    logger.debug('mulled-build commands: %s' % cmds)
    return utils.run(cmds)

@@ -1348,13 +1348,12 @@
 ide=
-'tmp'
+None
 , ch
@@ -2545,17 +2545,22 @@
  = '
-='.join(%5B
+%25s=%25s--%25s' %25 (
 name
@@ -2582,17 +2582,16 @@
 d_string
-%5D
 )%0A%0A    e
@@ -2927,24 +2927,204 @@
  tests)%0A
+    # Path to a file where we store the push commands to push all containers to%0A    # a Docker registry%0A    push_containers = os.environ.get('CONTAINER_PUSH_COMMANDS_PATH', False)%0A
 %0A    cmd
 s = %5B%0A  
@@ -3115,17 +3115,16 @@
 %0A    cmd
-s
  = %5B%0A   
@@ -3198,38 +3198,27 @@
   '-
--name-override', name_override
+n', 'biocontainers'
 ,%0A  
@@ -3245,28 +3245,99 @@
 s%0A    %5D%0A    
+if name_override:%0A        cmd += %5B'--name-override', name_override%5D%0A    
 cmd
-s
  += channel_
@@ -3348,17 +3348,16 @@
 %0A    cmd
-s
  += shle
@@ -3377,16 +3377,469 @@
 d_args)%0A
+    if push_containers:%0A        try:%0A            with open(push_containers, 'a+') as handle:%0A                handle.write('mulled-build push %25s -n biocontainers%5Cn' %25 (spec))%0A            logger.debug('Container push commands have been written to %22%25s%22', push_containers)%0A        except:%0A            logger.error('Could not write container push commands to %22%25s%22', push_containers)%0A    else:%0A        logger.debug('No container push commands are generated')%0A
     logg
@@ -3868,17 +3868,16 @@
  command
-s
 : %25s' %25 
@@ -3879,17 +3879,16 @@
 s' %25 cmd
-s
 )%0A    re
@@ -3905,11 +3905,10 @@
 .run(cmd
-s
 )%0A

Fix container tests and write push commands to a file