import unittest
from input.get.journal_fetcher import JournalFetcher
from input.interface import InputInterface
from input.publication import Publication

"""
Testing the Publication fetcher

Publication 1: 'https://doi.org/10.1021/acs.jcim.1c00203'
Publication 2: 'doi.org/10.1021/acs.jcim.1c00917'
Publication 3: '10.1038/nchem.1781'
Publication 4: '11.12/jaj'
Publication 5: '11.12/'
Publication 6: 'https://doi.org/10.1021/acs.jmedchem.0c01332' # Paper is a PDF
"""
# TODO: Testcases for:
#       - Specific Journals: Inherit from FetcherTestCase
#       - interface module-importer (test case)
#       - Error detection
#           - wrong/no Journal_fetchers
#           - wrong urls
#           - correct Types in publication
#       - Edgecases (i.e. paper as pdf, no connection, etc)


class InterfaceTestCase(unittest.TestCase):
    def setUp(self):
        self.assertEqual(InputInterface.instance, None)
        self.interface = InputInterface()

    def test_singleton(self):
        # interface should already be made in setUp()
        self.assertNotEqual(self.interface.instance, None)
        new_interface = InputInterface()
        self.assertEqual(self.interface, new_interface)
    
    # def test_imported_modules(self):
    #    fetchers = self.interface.get_supported_fetchers

class FetcherTestCase(unittest.TestCase):


    def can_use_url_test(self, fetcher : JournalFetcher, test_url: str, expected_res: bool):
        # Tests the 'can_use_url'-method
        self.assertEqual(fetcher.can_use_url(test_url), expected_res)


    def get_publication_test(self, fetcher : JournalFetcher, test_url: str, expected_res: Publication):
        """
        this test asserts that every variable is equals to the expected result
        """
        actual_res = fetcher.get_publication(test_url)
        self.assertEqual(actual_res.doi_url, expected_res.doi_url)
        self.assertEqual(actual_res.title, expected_res.title)
        self.assertEqual(actual_res.contributors, expected_res.contributors)
        self.assertEqual(actual_res.journal, expected_res.journal)
        self.assertEqual(actual_res.publication_date, expected_res.publication_date)
        self.assertEqual(actual_res.subjects, expected_res.subjects)

        # Checking for all references
        self.assertEqual(len(actual_res.references), len(expected_res.references))
        num_references = len(expected_res.references)
        for i in range(num_references):
            self.assertEqual(actual_res.references[i].doi_url,      expected_res.references[i].doi_url)
            self.assertEqual(actual_res.references[i].journal,      expected_res.references[i].journal)
            self.assertEqual(actual_res.references[i].contributors, expected_res.references[i].contributors)
            self.assertEqual(actual_res.references[i].cit_type,     expected_res.references[i].cit_type)

        # Checking for all citations
        self.assertEqual(len(actual_res.citations), len(expected_res.citations))
        num_citations = len(expected_res.citations)
        for i in range(num_citations):
            self.assertEqual(actual_res.citations[i].doi_url,      expected_res.citations[i].doi_url)
            self.assertEqual(actual_res.citations[i].journal,      expected_res.citations[i].journal)
            self.assertEqual(actual_res.citations[i].contributors, expected_res.citations[i].contributors)
            self.assertEqual(actual_res.citations[i].cit_type,     expected_res.citations[i].cit_type)


    def get_publication_exception_test(self, fetcher: JournalFetcher, test_url: str):
        # Ckecks 
        with self.assertRaises(ValueError):
            fetcher.get_publication(test_url)