#! /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', (['__name__'], {}), False, 'import logging\n'), (144, 'setuptools.setup', 'setup', ([], {'cmdclass': "{'install': SetupInstall, 'develop': SetupDevelop}"}), False, 'from setuptools import setup\n'), (17, 'os.path.join', 'os.path.join', (['"""nonperiodic"""', '"""no-periodicity.stan"""'], {}), False, 'import os\n'), (18, 'os.path.join', 'os.path.join', (['"""nonperiodic"""', '"""start-high-high-low.stan"""'], {}), False, 'import os\n'), (19, 'os.path.join', 'os.path.join', (['"""nonperiodic"""', '"""start-high-low-high.stan"""'], {}), False, 'import os\n'), (20, 'os.path.join', 'os.path.join', (['"""periodic"""', '"""start-high-low-low.stan"""'], {}), False, 'import os\n'), (21, 'os.path.join', 'os.path.join', (['"""untranslated"""', '"""gaussian-naive-bayes.stan"""'], {}), False, 'import os\n'), (22, 'os.path.join', 'os.path.join', (['"""translated"""', '"""periodic-gaussian-mixture.stan"""'], {}), False, 'import os\n'), (27, 'os.path.join', 'os.path.join', (['"""nonperiodic"""', '"""no-periodicity.pkl"""'], {}), False, 'import os\n'), (28, 'os.path.join', 'os.path.join', (['"""nonperiodic"""', '"""start-high-high-low.pkl"""'], {}), False, 'import os\n'), (29, 'os.path.join', 'os.path.join', (['"""nonperiodic"""', '"""start-high-low-high.pkl"""'], {}), False, 'import os\n'), (30, 'os.path.join', 'os.path.join', (['"""periodic"""', '"""start-high-low-low.pkl"""'], {}), False, 'import os\n'), (31, 'os.path.join', 'os.path.join', (['"""untranslated"""', '"""gaussian-naive-bayes.pkl"""'], {}), False, 'import os\n'), (32, 'os.path.join', 'os.path.join', (['"""translated"""', '"""periodic-gaussian-mixture.pkl"""'], {}), False, 'import os\n'), (40, 'os.path.dirname', 'os.path.dirname', (['pickle'], {}), False, 'import os\n'), (45, 'logging.info', 'logging.info', (['cmd'], {}), False, 'import logging\n'), (46, 'subprocess.call', 'subprocess.call', (['cmd'], {'shell': '(True)'}), False, 'import subprocess\n'), (52, 'importlib.reload', 'importlib.reload', (['site'], {}), 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', (['programs'], {'raise_on_error': '(False)', 'package_name': '"""flexbar"""', 'logger': 'logger'}), True, 'import pbio.misc.shell_utils as shell_utils\n'), (80, 'pbio.misc.shell_utils.check_programs_exist', 'shell_utils.check_programs_exist', (['programs'], {'raise_on_error': '(False)', 'package_name': '"""STAR"""', 'logger': 'logger'}), True, 'import pbio.misc.shell_utils as shell_utils\n'), (84, 'pbio.misc.shell_utils.check_programs_exist', 'shell_utils.check_programs_exist', (['programs'], {'raise_on_error': '(False)', 'package_name': '"""bowtie2"""', 'logger': 'logger'}), True, 'import pbio.misc.shell_utils as shell_utils\n'), (88, 'pbio.misc.shell_utils.check_programs_exist', 'shell_utils.check_programs_exist', (['programs'], {'raise_on_error': '(False)', 'package_name': '"""SAMtools"""', 'logger': 'logger'}), True, 'import pbio.misc.shell_utils as shell_utils\n'), (41, 'os.path.exists', 'os.path.exists', (['dirname'], {}), False, 'import os\n'), (42, 'os.makedirs', 'os.makedirs', (['dirname'], {}), False, 'import os\n'), (44, 'shlex.quote', 'shlex.quote', (['stan'], {}), False, 'import shlex\n'), (44, 'shlex.quote', 'shlex.quote', (['pickle'], {}), False, 'import shlex\n'), (57, 'os.path.join', 'os.path.join', (['"""rpbp_models"""', 's'], {}), False, 'import os\n'), (60, 'os.path.join', 'os.path.join', (['models_base', 's'], {}), False, 'import os\n'), (99, 'setuptools.command.install.install.initialize_options', 'install.initialize_options', (['self'], {}), True, 'from setuptools.command.install import install as install\n'), (103, 'setuptools.command.install.install.finalize_options', 'install.finalize_options', (['self'], {}), True, 'from setuptools.command.install import install as install\n'), (108, 'logging.getLevelName', 'logging.getLevelName', (['"""INFO"""'], {}), False, 'import logging\n'), (109, 'logging.basicConfig', 'logging.basicConfig', ([], {'level': 'level', 'format': '"""%(levelname)-8s : %(message)s"""'}), False, 'import logging\n'), (112, 'setuptools.command.install.install.run', 'install.run', (['self'], {}), True, 'from setuptools.command.install import install as install\n'), (125, 'setuptools.command.develop.develop.initialize_options', 'develop.initialize_options', (['self'], {}), True, 'from setuptools.command.develop import develop as develop\n'), (129, 'setuptools.command.develop.develop.finalize_options', 'develop.finalize_options', (['self'], {}), True, 'from setuptools.command.develop import develop as develop\n'), (134, 'logging.getLevelName', 'logging.getLevelName', (['"""INFO"""'], {}), False, 'import logging\n'), (135, 'logging.basicConfig', 'logging.basicConfig', ([], {'level': 'level', 'format': '"""%(levelname)-8s : %(message)s"""'}), False, 'import logging\n'), (138, 'setuptools.command.develop.develop.run', 'develop.run', (['self'], {}), True, 'from setuptools.command.develop import develop as develop\n'), (68, 'os.path.exists', 'os.path.exists', (['pickle'], {}), False, 'import os\n'), (70, 'logging.warning', 'logging.warning', (['msg'], {}), False, 'import logging\n'), (114, 'os.environ.get', 'os.environ.get', (['"""READTHEDOCS"""'], {}), False, 'import os\n'), (140, 'os.environ.get', 'os.environ.get', (['"""READTHEDOCS"""'], {}), False, 'import os\n')]