import pandas as pd

from utils.databases.superclasses.database_superclasses import Database
import pytest
import datetime

from utils.search_result_parsing import ProteomicSearchResultParser

example_db_dict = {
    'name': 'NCBI NR database', 'type': 'ncbi_nr', 'version': datetime.date(2018, 8, 8),
    'comment': 'test database containing the 100 first enries of the original database downloaded at 2018-08-08',
    'acc2tax': ['/path/to/test_dbs/prot2taxid/20180808/prot.accession2taxid.gz'],
    'taxdump_map': '/path/to/test_dbs/taxdump/20180808/taxdump.map.gz',
    'taxdump': '/path/to/test_dbs/taxdump/20180808/taxdump.tar.gz',
    'acc_regexp': '(?:^>|\\x01)([^\\s;]+)', 'acc_hit_regexp': '([^\\s;]+)', 'lca_level': 7,
    'scope': 'tax', 'db_schema_version': 2,
    'required_dbs': {
        "taxdump": {"version": datetime.date(2018, 8, 8)},
        "accession2taxid": {"version": datetime.date(2018, 8, 8)}
    }
}


class TestDatabaseObject:
    example_dict = example_db_dict
    incomplete_example_dict = example_dict.copy()
    del incomplete_example_dict['name']

    def test_build_from_dict(self):
        Database('dummy_path', self.example_dict)

    def test_incomplete_dict_fails(self):
        from utils.exceptions import DatabaseError
        with pytest.raises(DatabaseError):
            Database('dummy_path', self.incomplete_example_dict)

    def test_override_validation(self):
        Database('dummy_path', self.incomplete_example_dict, validate=False)


from utils.db_handling.maintenance.migrators import MigrateV01toV02
class TestMigrationV01toV02:
    yaml_dict = example_db_dict.copy()
    yaml_dict['db_schema_version'] = 1

    def test_migration_of_ncbinr(self):
        db_yaml_path = "nr/20180802/skip.yaml"
        from utils.databases.superclasses.database_superclasses import DbYamlInteractor
        yaml_obj = DbYamlInteractor(db_yaml_path, db_yaml_dict=self.yaml_dict)
        mig_obj = MigrateV01toV02([yaml_obj])
        set_of_paths_to_change = set(mig_obj.get_files_to_change())
        expected_set_of_paths_to_change = {"nr/20180802/skip.yaml"}
        # expected_set_of_paths_to_change = {"nr", "ncbi_nr", "nr/20180802", "nr/2018-08-08",
        #                                    "nr/20180802/taxdump.yaml", "ncbi_nr/2018-08-08/taxdump.yaml"}
        assert set_of_paths_to_change == expected_set_of_paths_to_change


class HelperTestingProteomicSearchResultParser(ProteomicSearchResultParser):
    def __init__(self, df):
        self.df_standard = df


def test_sanity_check_protein_acc_in_df():
    for p_list in [["w|a|sd"], ["def g"], ["efgh"+chr(1)]]:
        df = pd.DataFrame({'proteins': [p_list, ]})
        testing_parser = HelperTestingProteomicSearchResultParser(df)
        with pytest.raises(AttributeError):
            testing_parser.sanity_check_protein_acc_in_df()
    df = pd.DataFrame({'proteins': [
        ["wasd", "asdf"],
        ["defg"]
    ]})
    testing_parser = HelperTestingProteomicSearchResultParser(df)
    testing_parser.sanity_check_protein_acc_in_df()


def test_filter_out_decoys_drop_decoy_only_protein_groups():
    HelperTestingProteomicSearchResultParser.decoy_regex = 'DECOY$'
    df = pd.DataFrame({"proteins": [
        ["asd", "def"],
        ["rde_DECOY", "adi_DECOY"],
        ["trala_DECOY"]
    ]})
    parser = HelperTestingProteomicSearchResultParser(df)
    assert len(parser.filter_out_decoys(df)) == 1
