"""Class to add FSL installation to Dockerfile.

FSL wiki: https://fsl.fmrib.ox.ac.uk/fsl/fslwiki/
FSL license: https://fsl.fmrib.ox.ac.uk/fsl/fslwiki/Licence
"""
# Author: Jakub Kaczmarzyk <jakubk@mit.edu>

from __future__ import absolute_import, division, print_function
from distutils.version import LooseVersion
import logging

try:
    from urllib.parse import urljoin  # Python 3
except ImportError:
    from urlparse import urljoin  # Python 2

from neurodocker.utils import check_url, indent

logger = logging.getLogger(__name__)


class FSL(object):
    """Add Dockerfile instructions to install FSL.

    Parameters
    ----------
    version : str
        Version of FSL.
    pkg_manager : {'apt', 'yum'}
        Linux package manager.
    use_binaries : bool
        If true, use binaries from FSL's website (default true).
    use_installer : bool
        If true, install FSL using FSL's Python installer. Only works on
        CentOS/RHEL (default false).
    check_urls : bool
        If true, raise error if a URL used by this class responds with an error
        code.

    Notes
    -----
    Look into ReproNim/simple_workflow to learn how to install specific versions
    of FSL on Debian (https://github.com/ReproNim/simple_workflow).
    """
    def __init__(self, version, pkg_manager, use_binaries=True,
                 use_installer=False, check_urls=True):
        self.version = LooseVersion(version)
        self.pkg_manager = pkg_manager
        self.use_binaries = use_binaries
        self.use_installer = use_installer
        self.check_urls = check_urls

        self._check_args()
        self.cmd = self._create_cmd()

    def _check_args(self):
        """Raise `ValueError` if combinations of arguments are invalid."""
        if not self.use_binaries + self.use_installer:
            raise ValueError("Please specify installation method.")
        if self.use_binaries and self.use_installer:
            raise ValueError("More than one installation method specified.")
        if self.use_installer and self.pkg_manager != 'yum':
            raise ValueError("FSL's Python installer works only on "
                             "CentOS/RHEL-based systems.")
        return True

    def _create_cmd(self):
        """Return full Dockerfile instructions to install FSL."""
        comment = ("#-----------------------------------------------------------"
                   "\n# Install FSL v{}"
                   "\n# FSL is non-free. If you are considering commerical use"
                   "\n# of this Docker image, please consult the relevant license:"
                   "\n# https://fsl.fmrib.ox.ac.uk/fsl/fslwiki/Licence"
                   "\n#-----------------------------------------------------------"
                   "".format(self.version))
        if self.use_binaries:
            url = self._get_binaries_url()
            cmd = self.install_binaries(url)
        elif self.use_installer:
            cmd = self.install_with_pyinstaller(self.check_urls)
        return "\n".join((comment, cmd))

    @staticmethod
    def install_with_pyinstaller(check_urls=False):
        """Return Dockerfile instructions to install FSL using FSL's Python
        installer. This will install the latest version and only works on
        CentOS/RHEL.
        """
        workdir_cmd = "WORKDIR /opt"
        url = "https://fsl.fmrib.ox.ac.uk/fsldownloads/fslinstaller.py"
        if check_urls:
            check_url(url)
        cmd = ("curl -sSL -o fslinstaller.py {url}"
               "\n&& python fslinstaller.py --dest=/opt --quiet"
               "\n&& . /opt/fsl/etc/fslconf/fsl.sh"
               "\n&& rm -f fslinstaller.py"
               "".format(url=url))
        cmd = indent("RUN", cmd)

        path_cmd = ("FSLDIR=/opt/fsl"
                    "\n&& PATH=/opt/fsl/bin:$PATH")
        path_cmd = indent("ENV", path_cmd)

        return "\n".join((workdir_cmd, cmd, path_cmd))

    def _get_binaries_url(self):
        """Return URL to binaries for requested version."""
        base = "https://fsl.fmrib.ox.ac.uk/fsldownloads/"
        if self.version >= LooseVersion('5.0.9'):
            url = urljoin(base, "fsl-{ver}-centos6_64.tar.gz")
        else:
            url = urljoin(base, "oldversions/fsl-{ver}-centos5_64.tar.gz")
        url = url.format(ver=self.version)
        if self.check_urls:
            check_url(url)
        return url

    def install_binaries(self, url):
        """Return Dockerfile instructions to install FSL using binaries hosted
        on FSL's website.
        """
        from neurodocker.dockerfile import _add_to_entrypoint

        cmd = ('echo "Downloading FSL ..."'
               '\n&& curl -sSL {}'
               '\n| tar zx -C /opt'.format(url))

        if self.version >= LooseVersion('5.0.10'):
            fsl_python = "/opt/fsl/etc/fslconf/fslpython_install.sh"
            cmd +=  "\n&& /bin/bash {} -q -f /opt/fsl".format(fsl_python)

        ent_cmds = ["echo Some packages in this Docker container are non-free",
                    ("echo If you are considering commercial use of this"
                     " container, please consult the relevant license:"),
                     "echo https://fsl.fmrib.ox.ac.uk/fsl/fslwiki/Licence",
                     "source $FSLDIR/etc/fslconf/fsl.sh",]
        cmd += "\n&& {}".format(_add_to_entrypoint(ent_cmds, with_run=False))
        cmd = indent("RUN", cmd)

        env_cmd = ("FSLDIR=/opt/fsl"
                   "\nPATH=/opt/fsl/bin:$PATH")
        env_cmd = indent("ENV", env_cmd)

        return "\n".join((cmd, env_cmd))

@@ -492,16 +492,29 @@
 , indent
+, manage_pkgs
 %0A%0Alogger
@@ -4421,16 +4421,414 @@
 rn url%0A%0A
+    def _install_binaries_deps(self):%0A        %22%22%22Return command to install FreeSurfer dependencies. Use this for%0A        FreeSurfer binaries, not if attempting to build FreeSurfer from source.%0A        %22%22%22%0A        pkgs = %7B'apt': %22dc%22,%0A                'yum': %22bc%22%7D%0A%0A        cmd = %22%7Binstall%7D%5Cn&& %7Bclean%7D%22.format(**manage_pkgs%5Bself.pkg_manager%5D)%0A        return cmd.format(pkgs=pkgs%5Bself.pkg_manager%5D)%0A%0A
     def 
@@ -4856,16 +4856,16 @@
 , url):%0A
-
         
@@ -5049,16 +5049,61 @@
    cmd =
+ self._install_binaries_deps()%0A        cmd +=
  ('echo 
@@ -5140,16 +5140,17 @@
         
+ 
 '%5Cn&& cu
@@ -5161,16 +5161,17 @@
 sSL %7B%7D'%0A
+ 
         

install bc or dc