#! /usr/bin/env python3

import importlib
import logging
import os
import subprocess

from setuptools import setup
from setuptools.command.install import install as install
from setuptools.command.develop import develop as develop


logger = logging.getLogger(__name__)


stan_model_files = [
    os.path.join("nonperiodic", "no-periodicity.stan"),
    os.path.join("nonperiodic", "start-high-high-low.stan"),
    os.path.join("nonperiodic", "start-high-low-high.stan"),
    os.path.join("periodic", "start-high-low-low.stan"),
    os.path.join("untranslated", "gaussian-naive-bayes.stan"),
    os.path.join("translated", "periodic-gaussian-mixture.stan")
]


stan_pickle_files = [
    os.path.join("nonperiodic", "no-periodicity.pkl"),
    os.path.join("nonperiodic", "start-high-high-low.pkl"),
    os.path.join("nonperiodic", "start-high-low-high.pkl"),
    os.path.join("periodic", "start-high-low-low.pkl"),
    os.path.join("untranslated", "gaussian-naive-bayes.pkl"),
    os.path.join("translated", "periodic-gaussian-mixture.pkl")
]


def _pickle_it(stan, pickle):

    import shlex

    dirname = os.path.dirname(pickle)
    if not os.path.exists(dirname):
        os.makedirs(dirname)

    cmd = "pickle-stan {} {}".format(shlex.quote(stan), shlex.quote(pickle))
    logging.info(cmd)
    subprocess.call(cmd, shell=True)


def _post_install(force_recompile):

    import site
    importlib.reload(site)

    import pbio.ribo.ribo_filenames as filenames
    import pbio.misc.shell_utils as shell_utils
    
    smf = [os.path.join("rpbp_models", s) for s in stan_model_files]

    models_base = filenames.get_default_models_base()
    spf = [os.path.join(models_base, s) for s in stan_pickle_files]

    # Compile and pickle the Stan models
    if force_recompile:
        for stan, pickle in zip(smf, spf):
            _pickle_it(stan, pickle)
    else:  # default
        for stan, pickle in zip(smf, spf):
            if os.path.exists(pickle):
                msg = "A model already exists at: {}. Skipping.".format(pickle)
                logging.warning(msg)
                continue
            _pickle_it(stan, pickle)

    # Check for the prerequisite programs
    programs = ['flexbar']
    shell_utils.check_programs_exist(programs, raise_on_error=False,
                                     package_name='flexbar', logger=logger)
        
    programs = ['STAR']
    shell_utils.check_programs_exist(programs, raise_on_error=False,
                                     package_name='STAR', logger=logger)

    programs = ['bowtie2', 'bowtie2-build-s']
    shell_utils.check_programs_exist(programs, raise_on_error=False,
                                     package_name='bowtie2', logger=logger)

    programs = ['samtools']
    shell_utils.check_programs_exist(programs, raise_on_error=False,
                                     package_name='SAMtools', logger=logger)


class SetupInstall(install):

    user_options = install.user_options + [
        ('force-recompile', None, 'Set this flag to recompile the Stan models'),
    ]

    def initialize_options(self):
        install.initialize_options(self)
        self.force_recompile = None

    def finalize_options(self):
        install.finalize_options(self)

    def run(self):
        force_recompile = self.force_recompile  # 0 or 1

        level = logging.getLevelName("INFO")
        logging.basicConfig(level=level,
                            format='%(levelname)-8s : %(message)s')

        install.run(self)
        # skip if RTD
        if not os.environ.get('READTHEDOCS') == 'True':
            _post_install(force_recompile)


class SetupDevelop(develop):

    user_options = develop.user_options + [
        ('force-recompile', None, 'Set this flag to recompile the Stan models'),
    ]

    def initialize_options(self):
        develop.initialize_options(self)
        self.force_recompile = None

    def finalize_options(self):
        develop.finalize_options(self)

    def run(self):
        force_recompile = self.force_recompile  # 0 or 1

        level = logging.getLevelName("INFO")
        logging.basicConfig(level=level,
                            format='%(levelname)-8s : %(message)s')

        develop.run(self)
        # skip if RTD
        if not os.environ.get('READTHEDOCS') == 'True':
            _post_install(force_recompile)


setup(
    cmdclass={
        'install': SetupInstall,
        'develop': SetupDevelop
    }
)

[(13, 'logging.getLogger', 'logging.getLogger', False, 'import logging\n'), (144, 'setuptools.setup', 'setup', False, 'from setuptools import setup\n'), (17, 'os.path.join', 'os.path.join', False, 'import os\n'), (18, 'os.path.join', 'os.path.join', False, 'import os\n'), (19, 'os.path.join', 'os.path.join', False, 'import os\n'), (20, 'os.path.join', 'os.path.join', False, 'import os\n'), (21, 'os.path.join', 'os.path.join', False, 'import os\n'), (22, 'os.path.join', 'os.path.join', False, 'import os\n'), (27, 'os.path.join', 'os.path.join', False, 'import os\n'), (28, 'os.path.join', 'os.path.join', False, 'import os\n'), (29, 'os.path.join', 'os.path.join', False, 'import os\n'), (30, 'os.path.join', 'os.path.join', False, 'import os\n'), (31, 'os.path.join', 'os.path.join', False, 'import os\n'), (32, 'os.path.join', 'os.path.join', False, 'import os\n'), (40, 'os.path.dirname', 'os.path.dirname', False, 'import os\n'), (45, 'logging.info', 'logging.info', False, 'import logging\n'), (46, 'subprocess.call', 'subprocess.call', False, 'import subprocess\n'), (52, 'importlib.reload', 'importlib.reload', False, 'import importlib\n'), (59, 'pbio.ribo.ribo_filenames.get_default_models_base', 'filenames.get_default_models_base', True, 'import pbio.ribo.ribo_filenames as filenames\n'), (76, 'pbio.misc.shell_utils.check_programs_exist', 'shell_utils.check_programs_exist', True, 'import pbio.misc.shell_utils as shell_utils\n'), (80, 'pbio.misc.shell_utils.check_programs_exist', 'shell_utils.check_programs_exist', True, 'import pbio.misc.shell_utils as shell_utils\n'), (84, 'pbio.misc.shell_utils.check_programs_exist', 'shell_utils.check_programs_exist', True, 'import pbio.misc.shell_utils as shell_utils\n'), (88, 'pbio.misc.shell_utils.check_programs_exist', 'shell_utils.check_programs_exist', True, 'import pbio.misc.shell_utils as shell_utils\n'), (41, 'os.path.exists', 'os.path.exists', False, 'import os\n'), (42, 'os.makedirs', 'os.makedirs', False, 'import os\n'), (44, 'shlex.quote', 'shlex.quote', False, 'import shlex\n'), (44, 'shlex.quote', 'shlex.quote', False, 'import shlex\n'), (57, 'os.path.join', 'os.path.join', False, 'import os\n'), (60, 'os.path.join', 'os.path.join', False, 'import os\n'), (99, 'setuptools.command.install.install.initialize_options', 'install.initialize_options', True, 'from setuptools.command.install import install as install\n'), (103, 'setuptools.command.install.install.finalize_options', 'install.finalize_options', True, 'from setuptools.command.install import install as install\n'), (108, 'logging.getLevelName', 'logging.getLevelName', False, 'import logging\n'), (109, 'logging.basicConfig', 'logging.basicConfig', False, 'import logging\n'), (112, 'setuptools.command.install.install.run', 'install.run', True, 'from setuptools.command.install import install as install\n'), (125, 'setuptools.command.develop.develop.initialize_options', 'develop.initialize_options', True, 'from setuptools.command.develop import develop as develop\n'), (129, 'setuptools.command.develop.develop.finalize_options', 'develop.finalize_options', True, 'from setuptools.command.develop import develop as develop\n'), (134, 'logging.getLevelName', 'logging.getLevelName', False, 'import logging\n'), (135, 'logging.basicConfig', 'logging.basicConfig', False, 'import logging\n'), (138, 'setuptools.command.develop.develop.run', 'develop.run', True, 'from setuptools.command.develop import develop as develop\n'), (68, 'os.path.exists', 'os.path.exists', False, 'import os\n'), (70, 'logging.warning', 'logging.warning', False, 'import logging\n'), (114, 'os.environ.get', 'os.environ.get', False, 'import os\n'), (140, 'os.environ.get', 'os.environ.get', False, 'import os\n')]