"""riboSeqR Galaxy unit tests"""
import os
import shutil
import unittest
import tempfile
from riboseqr import utils, triplet, ribosome_profile

DATA_DIR = 'test-data'


class PrepareTestCase(unittest.TestCase):

    def test_process_args(self):
        """Test processing arguments. """
        # "ATG" -> c("ATG")
        rs = utils.process_args('ATG', ret_mode='charvector')
        self.assertEqual(rs, 'c("ATG")', 'Return string as a character vector.')

        # stop codons "TAG,TAA,TGA" -> c("TAG", "TAA", "TGA"). Also
        # replicate names, seqnames.
        rs = utils.process_args('TAG,TAA,TGA', ret_mode='charvector')
        self.assertEqual(
            rs, "c('TAG', 'TAA', 'TGA')",
            'Return comma separated strings as a character vector.')

        # "" -> None
        rs = utils.process_args('')
        self.assertIsNone(rs, 'Return empty string as None.')

        # "27,28" -> c(27, 28)
        rs = utils.process_args("27,28", ret_type='int', ret_mode='charvector')
        self.assertEqual(
            rs, "c(27, 28)", 'Return number strings as a character vector.')

        # "27,28" -> [27, 28]
        rs = utils.process_args("27,28", ret_type='int', ret_mode='list')
        self.assertEqual(rs, [27, 28], 'Return number strings as a list.')

        # "0,2" -> list(0,2)
        rs = utils.process_args("0,2", ret_type='int', ret_mode='listvector')
        self.assertEqual(
            rs, "list(0, 2)", 'Return number strings as a list vector.')

        # "50" -> 50
        rs = utils.process_args("50", ret_type='int')
        self.assertEqual(rs, 50, 'Return number string as a number.')

        # "-200" -> -200
        rs = utils.process_args("-200", ret_type='int')
        self.assertEqual(rs, -200, 'Return number string as a number.')

        # "TRUE" -> TRUE
        rs = utils.process_args("TRUE", ret_type='bool')
        self.assertEqual(rs, 'TRUE', 'Return bool string as bool.')

        # 'chlamy17,chlamy3' -> 'chlamy17,chlamy3' for ribo and rna names
        rs = utils.process_args('chlamy17,chlamy3')
        self.assertEqual(rs, 'chlamy17,chlamy3', 'Return csv string as string.')

        # 'chlamy17.idx, chlamy3.idx' -> ['chlamy17.idx', 'chlamy3.idx']
        rs = utils.process_args('chlamy17.idx, chlamy3.idx', ret_mode='list')
        self.assertEqual(rs, ['chlamy17.idx', 'chlamy3.idx'],
                         'Return files as a list.')


class TripletTestCase(unittest.TestCase):
    """Test triple periodicity"""
    html_file = None
    output_path = None
    rdata_load = os.path.join(DATA_DIR, 'Prepare riboSeqR input (R data file)')
    rdata_save = None
    include_lengths = '25:30'
    analyze_plot_lengths = '26:30'

    def setUp(self):
        self.html_file, self.output_path = tempfile.mkstemp()[1], tempfile.mkdtemp()
        self.rdata_save = os.path.join(self.output_path, 'Periodicity.rda')

    def tearDown(self):
        os.remove(self.html_file)
        shutil.rmtree(self.output_path)

    def test_triplet_periodicity(self):
        """Given a prepared RDA file, produce triplet periodicity output (R data file and plots).

        Note: only checks for the presence of program outputs
        """
        triplet.find_periodicity(
            rdata_load=self.rdata_load,
            fasta_file=os.path.join(DATA_DIR, 'rsem_chlamy236_deNovo.transcripts.fa'),
            include_lengths=self.include_lengths, analyze_plot_lengths=self.analyze_plot_lengths,
            html_file=self.html_file, output_path=self.output_path,
            rdata_save=self.rdata_save)

        for output in ('periodicity.R', 'Periodicity.rda', 'Periodicity-plot.pdf', 'Periodicity-plot.png'):
            self.assertTrue(os.path.exists(os.path.join(self.output_path, output)))

    def test_transcript_name(self):
        """Check that the transcript name is the same in the SAM and FASTA file. If not, raise an error."""
        self.assertRaises(
            triplet.TripletPeriodicityError, triplet.find_periodicity,
            rdata_load=self.rdata_load,
            fasta_file=os.path.join(DATA_DIR, 'rsem_chlamy236_deNovo.transcripts_mod.fa'),
            include_lengths=self.include_lengths, analyze_plot_lengths=self.analyze_plot_lengths,
            html_file=self.html_file, output_path=self.output_path,
            rdata_save=self.rdata_save)


class RibosomeProfileTestCase(unittest.TestCase):
    """Test plot ribosome profile."""
    html_file = None
    output_path = None
    rdata_load = os.path.join(DATA_DIR, 'Metagene analysis (R data file)')

    def setUp(self):
        self.html_file, self.output_path = tempfile.mkstemp()[1], tempfile.mkdtemp()

    def tearDown(self):
        os.remove(self.html_file)
        shutil.rmtree(self.output_path)

    def test_plot_ribosome_profile(self):
        """Given the right transcript name, produce a profile plot. """
        ribosome_profile.plot_transcript(
            rdata_load=self.rdata_load, transcript_name='CUFF.37930.1',
            transcript_length='27', transcript_cap='200', html_file=self.html_file,
            output_path=self.output_path)

        for output in ('ribosome-profile.R', 'Ribosome-profile-plot.pdf', 'Ribosome-profile-plot_1.png',
                       'Ribosome-profile-plot_2.png', 'Ribosome-profile-plot_3.png', 'Ribosome-profile-plot_4.png'):
            self.assertTrue(os.path.exists(os.path.join(self.output_path, output)))

    def test_invalid_transcript(self):
        """If a transcript is missing, produce an error message."""
        self.assertRaises(
            ribosome_profile.RibosomeProfileError, ribosome_profile.plot_transcript,
            rdata_load=self.rdata_load, transcript_name='MCUFF.37930.1',
            transcript_length='27', transcript_cap='200', html_file=self.html_file,
            output_path=self.output_path)
