import itertools
import os
import unittest

from mavis.annotate.base import ReferenceName
from mavis.annotate.protein import calculate_orf, Domain, DomainRegion
from mavis.annotate.variant import IndelCall
import timeout_decorator

from .mock import Mock, MockFunction

DATA_DIR = os.path.join(os.path.dirname(__file__), 'data')


class TestDomainAlignSeq(unittest.TestCase):
    def test_large_combinations_finishes_with_error(self):
        input_seq = (
            'MADDEDYEEVVEYYTEEVVYEEVPGETITKIYETTTTRTSDYEQSETSKPALAQPALAQPASAKPVERRKVIRKKVDPSK'
            'FMTPYIAHSQKMQDLFSPNKYKEKFEKTKGQPYASTTDTPELRRIKKVQDQLSEVKYRMDGDVAKTICHVDEKAKDIEHA'
            'KKVSQQVSKVLYKQNWEDTKDKYLLPPDAPELVQAVKNTAMFSKKLYTEDWEADKSLFYPYNDSPELRRVAQAQKALSDV'
            'AYKKGLAEQQAQFTPLADPPDIEFAKKVTNQVSKQKYKEDYENKIKGKWSETPCFEVANARMNADNISTRKYQEDFENMK'
            'DQIYFMQTETPEYKMNKKAGVAASKVKYKEDYEKNKGKADYNVLPASENPQLRQLKAAGDALSDKLYKENYEKTKAKSIN'
            'YCETPKFKLDTVLQNFSSDKKYKDSYLKDILGHYVGSFEDPYHSHCMKVTAQNSDKNYKAEYEEDRGKGFFPQTITQEYE'
            'AIKKLDQCKDHTYKVHPDKTKFTQVTDSPVLLQAQVNSKQLSDLNYKAKHESEKFKCHIPPDTPAFIQHKVNAYNLSDNL'
            'YKQDWEKSKAKKFDIKVDAIPLLAAKANTKNTSDVMYKKDYEKNKGKMIGVLSINDDPKMLHSLKVAKNQSDRLYKENYE'
            'KTKAKSMNYCETPKYQLDTQLKNFSEARYKDLYVKDVLGHYVGSMEDPYHTHCMKVAAQNSDKSYKAEYEEDKGKCYFPQ'
            'TITQEYEAIKKLDQCKDHTYKVHPDKTKFTAVTDSPVLLQAQLNTKQLSDLNYKAKHEGEKFKCHIPADAPQFIQHRVNA'
            'YNLSDNVYKQDWEKSKAKKFDIKVDAIPLLAAKANTKNTSDVMYKKDYEKSKGKMIGALSINDDPKMLHSLKTAKNQSDR'
            'EYRKDYEKSKTIYTAPLDMLQVTQAKKSQAIASDVDYKHILHSYSYPPDSINVDLAKKAYALQSDVEYKADYNSWMKGCG'
            'WVPFGSLEMEKAKRASDILNEKKYRQHPDTLKFTSIEDAPITVQSKINQAQRSDIAYKAKGEEIIHKYNLPPDLPQFIQA'
            'KVNAYNISENMYKADLKDLSKKGYDLRTDAIPIRAAKAARQAASDVQYKKDYEKAKGKMVGFQSLQDDPKLVHYMNVAKI'
            'QSDREYKKDYEKTKSKYNTPHDMFNVVAAKKAQDVVSNVNYKHSLHHYTYLPDAMDLELSKNMMQIQSDNVYKEDYNNWM'
            'KGIGWIPIGSLDVEKVKKAGDALNEKKYRQHPDTLKFTSIVDSPVMVQAKQNTKQVSDILYKAKGEDVKHKYTMSPDLPQ'
            'FLQAKCNAYNISDVCYKRDWYDLIAKGNNVLGDAIPITAAKASRNIASDYKYKEAYEKSKGKHVGFRSLQDDPKLVHYMN'
            'VAKLQSDREYKKNYENTKTSYHTPGDMVSITAAKMAQDVATNVNYKQPLHHYTYLPDAMSLEHTRNVNQIQSDNVYKDEY'
            'NSFLKGIGWIPIGSLEVEKVKKAGDALNERKYRQHPDTVKFTSVPDSMGMVLAQHNTKQLSDLNYKVEGEKLKHKYTIDP'
            'ELPQFIQAKVNALNMSDAHYKADWKKTIAKGYDLRPDAIPIVAAKSSRNIASDCKYKEAYEKAKGKQVGFLSLQDDPKLV'
            'HYMNVAKIQSDREYKKGYEASKTKYHTPLDMVSVTAAKKSQEVATNANYRQSYHHYTLLPDALNVEHSRNAMQIQSDNLY'
            'KSDFTNWMKGIGWVPIESLEVEKAKKAGEILSEKKYRQHPEKLKFTYAMDTMEQALNKSNKLNMDKRLYTEKWNKDKTTI'
            'HVMPDTPDILLSRVNQITMSDKLYKAGWEEEKKKGYDLRPDAIAIKAARASRDIASDYKYKKAYEQAKGKHIGFRSLEDD'
            'PKLVHFMQVAKMQSDREYKKGYEKSKTSFHTPVDMLSVVAAKKSQEVATNANYRNVIHTYNMLPDAMSFELAKNMMQIQS'
            'DNQYKADYADFMKGIGWLPLGSLEAEKNKKAMEIISEKKYRQHPDTLKYSTLMDSMNMVLAQNNAKIMNEHLYKQAWEAD'
            'KTKVHIMPDIPQIILAKANAINMSDKLYKLSLEESKKKGYDLRPDAIPIKAAKASRDIASDYKYKYNYEKGKGKMVGFRS'
            'LEDDPKLVHSMQVAKMQSDREYKKNYENTKTSYHTPADMLSVTAAKDAQANITNTNYKHLIHKYILLPDAMNIELTRNMN'
            'RIQSDNEYKQDYNEWYKGLGWSPAGSLEVEKAKKATEYASDQKYRQHPSNFQFKKLTDSMDMVLAKQNAHTMNKHLYTID'
            'WNKDKTKIHVMPDTPDILQAKQNQTLYSQKLYKLGWEEALKKGYDLPVDAISVQLAKASRDIASDYKYKQGYRKQLGHHV'
            'GFRSLQDDPKLVLSMNVAKMQSEREYKKDFEKWKTKFSSPVDMLGVVLAKKCQELVSDVDYKNYLHQWTCLPDQNDVVQA'
            'KKVYELQSENLYKSDLEWLRGIGWSPLGSLEAEKNKRASEIISEKKYRQPPDRNKFTSIPDAMDIVLAKTNAKNRSDRLY'
            'REAWDKDKTQIHIMPDTPDIVLAKANLINTSDKLYRMGYEELKRKGYDLPVDAIPIKAAKASREIASEYKYKEGFRKQLG'
            'HHIGARNIEDDPKMMWSMHVAKIQSDREYKKDFEKWKTKFSSPVDMLGVVLAKKCQTLVSDVDYKNYLHQWTCLPDQSDV'
            'IHARQAYDLQSDNLYKSDLQWLKGIGWMTSGSLEDEKNKRATQILSDHVYRQHPDQFKFSSLMDSIPMVLAKNNAITMNH'
            'RLYTEAWDKDKTTVHIMPDTPEVLLAKQNKVNYSEKLYKLGLEEAKRKGYDMRVDAIPIKAAKASRDIASEFKYKEGYRK'
            'QLGHHIGARAIRDDPKMMWSMHVAKIQSDREYKKDFEKWKTKFSSPVDMLGVVLAKKCQTLVSDVDYKNYLHQWTCLPDQ'
            'SDVIHARQAYDLQSDNMYKSDLQWMRGIGWVSIGSLDVEKCKRATEILSDKIYRQPPDRFKFTSVTDSLEQVLAKNNAIT'
            'MNKRLYTEAWDKDKTQIHIMPDTPEIMLARMNKINYSESLYKLANEEAKKKGYDLRSDAIPIVAAKASRDIISDYKYKDG'
            'YCKQLGHHIGARNIEDDPKMMWSMHVAKIQSDREYKKDFEKWKTKFSSPVDMLGVVLAKKCQTLVSDVDYKNYLHEWTCL'
            'PDQSDVIHARQAYDLQSDNIYKSDLQWLRGIGWVPIGSMDVVKCKRATEILSDNIYRQPPDKLKFTSVTDSLEQVLAKNN'
            'ALNMNKRLYTEAWDKDKTQIHIMPDTPEIMLARQNKINYSETLYKLANEEAKKKGYDLRSDAIPIVAAKASRDVISDYKY'
            'KDGYRKQLGHHIGARNIEDDPKMMWSMHVAKIQSDREYKKDFEKWKTKFSSPVDMLGVVLAKKCQTLVSDVDYKNYLHEW'
            'TCLPDQNDVIHARQAYDLQSDNIYKSDLQWLRGIGWVPIGSMDVVKCKRAAEILSDNIYRQPPDKLKFTSVTDSLEQVLA'
            'KNNALNMNKRLYTEAWDKDKTQVHIMPDTPEIMLARQNKINYSESLYRQAMEEAKKEGYDLRSDAIPIVAAKASRDIASD'
            'YKYKEAYRKQLGHHIGARAVHDDPKIMWSLHIAKVQSDREYKKDFEKYKTRYSSPVDMLGIVLAKKCQTLVSDVDYKHPL'
            'HEWICLPDQNDIIHARKAYDLQSDNLYKSDLEWMKGIGWVPIDSLEVVRAKRAGELLSDTIYRQRPETLKFTSITDTPEQ'
            'VLAKNNALNMNKRLYTEAWDNDKKTIHVMPDTPEIMLAKLNRINYSDKLYKLALEESKKEGYDLRLDAIPIQAAKASRDI'
            'ASDYKYKEGYRKQLGHHIGARNIKDDPKMMWSIHVAKIQSDREYKKEFEKWKTKFSSPVDMLGVVLAKKCQILVSDIDYK'
            'HPLHEWTCLPDQNDVIQARKAYDLQSDAIYKSDLEWLRGIGWVPIGSVEVEKVKRAGEILSDRKYRQPADQLKFTCITDT'
            'PEIVLAKNNALTMSKHLYTEAWDADKTSIHVMPDTPDILLAKSNSANISQKLYTKGWDESKMKDYDLRADAISIKSAKAS'
            'RDIASDYKYKEAYEKQKGHHIGAQSIEDDPKIMCAIHAGKIQSEREYKKEFQKWKTKFSSPVDMLSILLAKKCQTLVTDI'
            'DYRNYLHEWTCMPDQNDIIQAKKAYDLQSDSVYKADLEWLRGIGWMPEGSVEMNRVKVAQDLVNERLYRTRPEALSFTSI'
            'VDTPEVVLAKANSLQISEKLYQEAWNKDKSNITIPSDTPEMLQAHINALQISNKLYQKDWNDAKQKGYDIRADAIEIKHA'
            'KASREIASEYKYKEGYRKQLGHHMGFRTLQDDPKSVWAIHAAKIQSDREYKKAYEKSKGIHNTPLDMMSIVQAKKCQVLV'
            'SDIDYRNYLHQWTCLPDQNDVIQAKKAYDLQSDNLYKSDLEWLKGIGWLPEGSVEVMRVKNAQNLLNERLYRIKPEALKF'
            'TSIVDTPEVIQAKINAVQISEPLYRDAWEKEKANVNVPADTPLMLQSKINALQISNKRYQQAWEDVKMTGYDLRADAIGI'
            'QHAKASRDIASDYLYKTAYEKQKGHYIGCRSAKEDPKLVWAANVLKMQNDRLYKKAYNDHKAKISIPVDMVSISAAKEGQ'
            'ALASDVDYRHYLHHWSCFPDQNDVIQARKAYDLQSDSVYKADLEWLRGIGWMPEGSVEMNRVKVAQDLVNERLYRTRPEA'
            'LSFTSIVDTPEVVLAKANSLQISEKLYQEAWNKDKSNITIPSDTPEMLQAHINALQISNKLYQKDWNDTKQKGYDIRADA'
            'IEIKHAKASREIASEYKYKEGYRKQLGHHMGFRTLQDDPKSVWAIHAAKIQSDREYKKAYEKSKGIHNTPLDMMSIVQAK'
            'KCQVLVSDIDYRNYLHQWTCLPDQNDVIQAKKAYDLQSDNLYKSDLEWLKGIGWLPEGSVEVMRVKNAQNLLNERLYRIK'
            'PEALKFTSIVDTPEVIQAKINAVQISEPLYRNAWEKEKANVNVPADTPLMLQSKINALQISNKRYQQAWEDVKMTGYDLR'
            'ADAIGIQHAKASRDIASDYLYKTAYEKQKGHYIGCRSAKEDPKLVWAANVLKMQNDRLYKKAYNDHKAKISIPVDMVSIS'
            'AAKEGQALASDVDYRHYLHHWSCFPDQNDVIQARKAYDLQSDSVYKADLEWLRGIGWMPEGSVEMNRVKVAQDLVNERLY'
            'RTRPEALSFTSIVDTPEVVLAKANSLQISEKLYQEAWNKDKSNITIPSDTPEMLQAHINALQISNKLYQKDWNDTKQKGY'
            'DIRADAIEIKHAKASREIASEYKYKEGYRKQLGHHMGFRTLQDDPKSVWAIHAAKIQSDREYKKAYEKSKGIHNTPLDMM'
            'SIVQAKKCQVLVSDIDYRNYLHQWTCLPDQNDVIQAKKAYDLQSDNLYKSDLEWLKGIGWLPEGSVEVMRVKNAQNLLNE'
            'RLYRIKPEALKFTSIVDTPEVIQAKINAVQISEPLYRDAWEKEKANVNVPADTPLMLQSKINALQISNKRYQQAWEDVKM'
            'TGYDLRADAIGIQHAKASRDIASDYLYKTAYEKQKGHYIGCRSAKEDPKLVWAANVLKMQNDRLYKKAYNDHKAKISIPV'
            'DMVSISAAKEGQALASDVDYRHYLHRWSCFPDQNDVIQARKAYDLQSDALYKADLEWLRGIGWMPQGSPEVLRVKNAQNI'
            'FCDSVYRTPVVNLKYTSIVDTPEVVLAKSNAENISIPKYREVWDKDKTSIHIMPDTPEINLARANALNVSNKLYREGWDE'
            'MKAGCDVRLDAIPIQAAKASREIASDYKYKLDHEKQKGHYVGTLTARDDNKIRWALIADKLQNEREYRLDWAKWKAKIQS'
            'PVDMLSILHSKNSQALVSDMDYRNYLHQWTCMPDQNDVIQAKKAYELQSDNVYKADLEWLRGIGWMPNDSVSVNHAKHAA'
            'DIFSEKKYRTKIETLNFTPVDDRVDYVTAKQSGEILDDIKYRKDWNATKSKYTLTETPLLHTAQEAARILDQYLYKEGWE'
            'RQKATGYILPPDAVPFVHAHHCNDVQSELKYKAEHVKQKGHYVGVPTMRDDPKLVWFEHAGQIQNERLYKEDYHKTKAKI'
            'NIPADMVSVLAAKQGQTLVSDIDYRNYLHQWMCHPDQNDVIQARKAYDLQSDNVYRADLEWLRGIGWIPLDSVDHVRVTK'
            'NQEMMSQIKYKKNALENYPNFRSVVDPPEIVLAKINSVNQSDVKYKETFNKAKGKYTFSPDTPHISHSKDMGKLYSTILY'
            'KGAWEGTKAYGYTLDERYIPIVGAKHADLVNSELKYKETYEKQKGHYLAGKVIGEFPGVVHCLDFQKMRSALNYRKHYED'
            'TKANVHIPNDMMNHVLAKRCQYILSDLEYRHYFHQWTSLLEEPNVIRVRNAQEILSDNVYKDDLNWLKGIGCYVWDTPQI'
            'LHAKKSYDLQSQLQYTAAGKENLQNYNLVTDTPLYVTAVQSGINASEVKYKENYHQIKDKYTTVLETVDYDRTRNLKNLY'
            'SSNLYKEAWDRVKATSYILPSSTLSLTHAKNQKHLASHIKYREEYEKFKALYTLPRSVDDDPNTARCLRVGKLNIDRLYR'
            'SVYEKNKMKIHIVPDMVEMVTAKDSQKKVSEIDYRLRLHEWICHPDLQVNDHVRKVTDQISDIVYKDDLNWLKGIGCYVW'
            'DTPEILHAKHAYDLRDDIKYKAHMLKTRNDYKLVTDTPVYVQAVKSGKQLSDAVYHYDYVHSVRGKVAPTTKTVDLDRAL'
            'HAYKLQSSNLYKTSLRTLPTGYRLPGDTPHFKHIKDTRYMSSYFKYKEAYEHTKAYGYTLGPKDVPFVHVRRVNNVTSER'
            'LYRELYHKLKDKIHTTPDTPEIRQVKKTQEAVSELIYKSDFFKMQGHMISLPYTPQVIHCRYVGDITSDIKYKEDLQVLK'
            'GFGCFLYDTPDMVRSRHLRKLWSNYLYTDKARKMRDKYKVVLDTPEYRKVQELKTHLSELVYRAAGKKQKSIFTSVPDTP'
            'DLLRAKRGQKLQSQYLYVELATKERPHHHAGNQTTALKHAKDVKDMVSEKKYKIQYEKMKDKYTPVPDTPILIRAKRAYW'
            'NASDLRYKETFQKTKGKYHTVKDALDIVYHRKVTDDISKIKYKENYMSQLGIWRSIPDRPEHFHHRAVTDTVSDVKYKED'
            'LTWLKGIGCYAYDTPDFTLAEKNKTLYSKYKYKEVFERTKSDFKYVADSPINRHFKYATQLMNERKYKSSAKMFLQHGCN'
            'EILRPDMLTALYNSHMWSQIKYRKNYEKSKDKFTSIVDTPEHLRTTKVNKQISDILYKLEYNKAKPRGYTTIHDTPMLLH'
            'VRKVKDEVSDLKYKEVYQRNKSNCTIEPDAVHIKAAKDAYKVNTNLDYKKQYEANKAHWKWTPDRPDFLQAAKSSLQQSD'
            'FEYKLDREFLKGCKLSVTDDKNTVLALRNTLIESDLKYKEKHVKERGTCHAVPDTPQILLAKTVSNLVSENKYKDHVKKH'
            'LAQGSYTTLPETRDTVHVKEVTKHVSDTNYKKKFVKEKGKSNYSIMLEPPEVKHAMEVAKKQSDVAYRKDAKENLHYTTV'
            'ADRPDIKKATQAAKQASEVEYRAKHRKEGSHGLSMLGRPDIEMAKKAAKLSSQVKYRENFDKEKGKTPKYNPKDSQLYKV'
            'MKDANNLASEVKYKADLKKLHKPVTDMKESLIMNHVLNTSQLASSYQYKKKYEKSKGHYHTIPDNLEQLHLKEATELQSI'
            'VKYKEKYEKERGKPMLDFETPTYITAKESQQMQSGKEYRKDYEESIKGRNLTGLEVTPALLHVKYATKIASEKEYRKDLE'
            'ESIRGKGLTEMEDTPDMLRAKNATQILNEKEYKRDLELEVKGRGLNAMANETPDFMRARNATDIASQIKYKQSAEMEKAN'
            'FTSVVDTPEIIHAQQVKNLSSQKKYKEDAEKSMSYYETVLDTPEIQRVRENQKNFSLLQYQCDLKNSKGKITVVQDTPEI'
            'LRVKENQKNFSSVLYKEDVSPGTAIGKTPEMMRVKQTQDHISSVKYKEAIGQGTPIPDLPEVKRVKETQKHISSVMYKEN'
            'LGTGIPTTVTPEIERVKRNQENFSSVLYKENLGKGIPTPITPEMERVKRNQENFSSILYKENLSKGTPLPVTPEMERVKL'
            'NQENFSSVLYKENVGKGIPIPITPEMERVKHNQENFSSVLYKENLGTGIPIPITPEMQRVKHNQENLSSVLYKENMGKGT'
            'PLPVTPEMERVKHNQENISSVLYKENMGKGTPLPVTPEMERVKHNQENISSVLYKENMGKGTPLAVTPEMERVKHNQENI'
            'SSVLYKENVGKATATPVTPEMQRVKRNQENISSVLYKENLGKATPTPFTPEMERVKRNQENFSSVLYKENMRKATPTPVT'
            'PEMERAKRNQENISSVLYSDSFRKQIQGKAAYVLDTPEMRRVRETQRHISTVKYHEDFEKHKGCFTPVVTDPITERVKKN'
            'MQDFSDINYRGIQRKVVEMEQKRNDQDQETITGLRVWRTNPGSVFDYDPAEDNIQSRSLHMINVQAQRRSREQSRSASAL'
            'SISGGEEKSEHSEAPDHHLSTYSDGGVFAVSTAYKHAKTTELPQQRSSSVATQQTTVSSIPSHPSTAGKIFRAMYDYMAA'
            'DADEVSFKDGDAIINVQAIDEGWMYGTVQRTGRTGMLPANYVEAI*'
        )

        region_seqs = [
            'TPYIAHSQKMQDLFSPNKYKEKFEKTKG',
            'DTPELRRIKKVQDQLSEVKYRMDGD',
            'DIEHAKKVSQQVSKVLYKQNWEDTK',
            'DAPELVQAVKNTAMFSKKLYTEDWEADK',
            'DPPDIEFAKKVTNQVSKQKYKEDYEN',
            'ETPEYKMNKKAGVAASKVKYKEDYEKNKG',
            'NPQLRQLKAAGDALSDKLYKENYEKTKA',
            'DSPVLLQAQVNSKQLSDLNYKAKHESEK',
            'DTPAFIQHKVNAYNLSDNLYKQDWEKSKA',
            'DAIPLLAAKANTKNTSDVMYKKDYEKNKG',
            'DDPKMLHSLKVAKNQSDRLYKENYEKTKA',
            'DAPQFIQHRVNAYNLSDNVYKQDWEKSKA',
            'DAIPLLAAKANTKNTSDVMYKKDYEKSKG',
            'DDPKMLHSLKTAKNQSDREYRKDYEKSK',
            'DSINVDLAKKAYALQSDVEYKADYNSW',
            'DAIPIRAAKAARQAASDVQYKKDYEKAKG',
            'DDPKLVHYMNVAKIQSDREYKKDYEKTKS',
            'DAMDLELSKNMMQIQSDNVYKEDYNNWM',
            'DSPVMVQAKQNTKQVSDILYKAKGEDVKH',
            'DLPQFLQAKCNAYNISDVCYKRDWYD',
            'DAIPITAAKASRNIASDYKYKEAYEKSKG',
            'DDPKLVHYMNVAKLQSDREYKKNYENTK',
            'PQFIQAKVNALNMSDAHYKADWKKTI',
            'DAIPIVAAKSSRNIASDCKYKEAYEKAKG',
            'DDPKLVHYMNVAKIQSDREYKKGYEASK',
            'DTPDILLSRVNQITMSDKLYKAGWEEEKK',
            'DAIAIKAARASRDIASDYKYKKAYEQAKG',
            'DDPKLVHFMQVAKMQSDREYKKGYEKSK',
            'DAMSFELAKNMMQIQSDNQYKADYA',
            'DSMNMVLAQNNAKIMNEHLYKQAWEADK',
            'DIPQIILAKANAINMSDKLYKLSLEESKK',
            'DAIPIKAAKASRDIASDYKYKYNYEKGKG',
            'DDPKLVHSMQVAKMQSDREYKKNYENTK',
            'DSMDMVLAKQNAHTMNKHLYTIDWNKDK',
            'DTPDILQAKQNQTLYSQKLYKLGWEEA',
            'DAISVQLAKASRDIASDYKYKQGYRKQLG',
            'DDPKLVLSMNVAKMQSEREYKKDFEKWK',
            'QNDVVQAKKVYELQSENLYKSDLEWLRG',
            'DAMDIVLAKTNAKNRSDRLYREAWDKDK',
            'DTPDIVLAKANLINTSDKLYRMGYEELK',
            'DAIPIKAAKASREIASEYKYKEGFRKQLG',
            'DDPKMMWSMHVAKIQSDREYKKDFEKWK',
            'DVIHARQAYDLQSDNLYKSDLQWLKG',
            'DSIPMVLAKNNAITMNHRLYTEAWDKDK',
            'DTPEVLLAKQNKVNYSEKLYKLGLEEAK',
            'DDPKMMWSMHVAKIQSDREYKKDFEKWK',
            'DSLEQVLAKNNAITMNKRLYTEAWDKDK',
            'DTPEIMLARMNKINYSESLYKLANEEAK',
            'DDPKMMWSMHVAKIQSDREYKKDFEKWK',
            'DSLEQVLAKNNALNMNKRLYTEAWDKDK',
            'DTPEIMLARQNKINYSETLYKLANEEAK',
            'DAIPIVAAKASRDVISDYKYKDGYRKQLG',
            'DDPKMMWSMHVAKIQSDREYKKDFEKWK',
            'DSLEQVLAKNNALNMNKRLYTEAWDKDK',
            'DTPEIMLARQNKINYSESLYRQAMEEAKK',
            'DAIPIVAAKASRDIASDYKYKEAYRKQLG',
            'DDPKIMWSLHIAKVQSDREYKKDFEKYK',
            'QNDIIHARKAYDLQSDNLYKSDLEWMKG',
            'DTPEQVLAKNNALNMNKRLYTEAWDNDKK',
            'DTPEIMLAKLNRINYSDKLYKLALEESKK',
            'DAIPIQAAKASRDIASDYKYKEGYRKQLG',
            'DDPKMMWSIHVAKIQSDREYKKEFEKWK',
            'DTPEIVLAKNNALTMSKHLYTEAWDADK',
            'DTPDILLAKSNSANISQKLYTKGWDESK',
            'DAISIKSAKASRDIASDYKYKEAYEKQKG',
            'DDPKIMCAIHAGKIQSEREYKKEFQKWK',
            'QNDIIQAKKAYDLQSDSVYKADLEWLRG',
            'DTPEVVLAKANSLQISEKLYQEAWNKDKS',
            'DTPEMLQAHINALQISNKLYQKDWNDAK',
            'DAIEIKHAKASREIASEYKYKEGYRKQLG',
            'DDPKSVWAIHAAKIQSDREYKKAYEKSKG',
            'NDVIQAKKAYDLQSDNLYKSDLEWLKG',
            'DTPEVIQAKINAVQISEPLYRDAWEKEKA',
            'DAIGIQHAKASRDIASDYLYKTAYEKQKG',
            'NDVIQARKAYDLQSDSVYKADLEWLRG',
            'DTPEVVLAKANSLQISEKLYQEAWNKDKS',
            'DTPEMLQAHINALQISNKLYQKDWNDTK',
            'DAIEIKHAKASREIASEYKYKEGYRKQLG',
            'DDPKSVWAIHAAKIQSDREYKKAYEKSKG',
            'NDVIQAKKAYDLQSDNLYKSDLEWLKG',
            'DTPEVIQAKINAVQISEPLYRNAWEKEKA',
            'DAIGIQHAKASRDIASDYLYKTAYEKQKG',
            'NDVIQARKAYDLQSDSVYKADLEWLRG',
            'DTPEVVLAKANSLQISEKLYQEAWNKDKS',
            'DTPEMLQAHINALQISNKLYQKDWNDTK',
            'DAIEIKHAKASREIASEYKYKEGYRKQLG',
            'DDPKSVWAIHAAKIQSDREYKKAYEKSKG',
            'NDVIQAKKAYDLQSDNLYKSDLEWLKG',
            'DTPEVIQAKINAVQISEPLYRDAWEKEKA',
            'DAIGIQHAKASRDIASDYLYKTAYEKQKG',
            'NDVIQARKAYDLQSDALYKADLEWLRG',
            'DTPEVVLAKSNAENISIPKYREVWDKDK',
            'DTPEINLARANALNVSNKLYREGWDEMKA',
            'DAIPIQAAKASREIASDYKYKLDHEKQKG',
            'NDVIQAKKAYELQSDNVYKADLEWLRG',
            'DRVDYVTAKQSGEILDDIKYRKDWNATKS',
            'DAVPFVHAHHCNDVQSELKYKAEHVKQKG',
            'DDPKLVWFEHAGQIQNERLYKEDYHKTKA',
            'NDVIQARKAYDLQSDNVYRADLEWLRG',
            'DPPEIVLAKINSVNQSDVKYKETFNKAKG',
            'DTPHISHSKDMGKLYSTILYKGAWEGTKA',
            'PIVGAKHADLVNSELKYKETYEKQKG',
            'PNVIRVRNAQEILSDNVYKDDLNWLKG',
            'DTPQILHAKKSYDLQSQLQYTAAGKEN',
            'DTPLYVTAVQSGINASEVKYKENYHQIK',
            'LSLTHAKNQKHLASHIKYREEYEKFKA',
            'DTPEILHAKHAYDLRDDIKYKAH',
            'DTPHFKHIKDTRYMSSYFKYKEAYEHTKA',
            'DTPEIRQVKKTQEAVSELIYKSDFFKMQG',
            'TPQVIHCRYVGDITSDIKYKEDLQVLK',
            'DTPDMVRSRHLRKLWSNYLYTDKARKMR',
            'DTPILIRAKRAYWNASDLRYKETFQKTKG',
            'DRPEHFHHRAVTDTVSDVKYKEDLTWLKG',
            'DTPDFTLAEKNKTLYSKYKYKEVFERTKS',
            'RPDMLTALYNSHMWSQIKYRKNYEKSK',
            'DTPEHLRTTKVNKQISDILYKLEYNKAK',
            'DTPMLLHVRKVKDEVSDLKYKEVYQRNK',
            'DTPQILLAKTVSNLVSENKYKDHVKK',
            'ETRDTVHVKEVTKHVSDTNYKKKFVKEKG',
            'RPDIEMAKKAAKLSSQVKYRENFDKEKG',
            'DNLEQLHLKEATELQSIVKYKEKYEKERG',
            'ETPTYITAKESQQMQSGKEYRKDYEESI',
            'TPALLHVKYATKIASEKEYRKDLEES',
            'DTPDMLRAKNATQILNEKEYKRDLE',
            'ETPDFMRARNATDIASQIKYKQSAEMEKA',
            'DTPEIIHAQQVKNLSSQKKYKEDAEKSM',
            'DTPEIQRVRENQKNFSLLQYQCDLKNSKG',
            'DTPEILRVKENQKNFSSVLYKED',
            'TPEMMRVKQTQDHISSVKYKEA',
            'TPEIERVKRNQENFSSVLYKENLGK',
            'TPEMERVKRNQENFSSILYKENL',
            'TPEMERVKLNQENFSSVLYKEN',
            'TPEMERVKHNQENFSSVLYKEN',
            'TPEMQRVKHNQENLSSVLYKENM',
            'TPEMERVKHNQENISSVLYKENM',
            'TPEMERVKHNQENISSVLYKENM',
            'TPEMERVKHNQENISSVLYKENVGK',
            'TPEMQRVKRNQENISSVLYKENLGKA',
            'TPEMERVKRNQENFSSVLYKENMRKA',
            'TPEMERAKRNQENISSVLYSDSFRKQI',
            'DTPEMRRVRETQRHISTVKYHEDFEKHKG',
        ]
        regions = []
        p = 1
        for seq in region_seqs:
            regions.append(DomainRegion(p, p + len(seq) - 1, seq=seq))
            p += len(seq)
        d = Domain('name', regions=regions)
        with self.assertRaises(UserWarning):
            d.align_seq(input_seq)


class TestCalculateORF(unittest.TestCase):
    def setUp(self):
        # load the sequence
        with open(os.path.join(DATA_DIR, 'calc_orf_test_sequence.fa'), 'r') as fh:
            self.seq = fh.readlines()[0].strip()

    @timeout_decorator.timeout(20)
    def test_very_long(self):
        calculate_orf(self.seq, 300)


class TestReferenceName(unittest.TestCase):
    def test_naked_vs_naked_str(self):
        self.assertEqual('1', ReferenceName('1'))
        self.assertNotEqual('2', ReferenceName('1'))
        self.assertTrue(ReferenceName('1') == '1')
        self.assertTrue(ReferenceName('1') != '2')

    def test_naked_vs_prefixed_str(self):
        self.assertEqual('chr1', ReferenceName('1'))
        self.assertNotEqual('chr2', ReferenceName('1'))
        self.assertTrue(ReferenceName('1') == 'chr1')
        self.assertTrue(ReferenceName('1') != 'chr2')

    def test_prefixed_vs_prefixed_str(self):
        self.assertEqual('chr1', ReferenceName('chr1'))
        self.assertNotEqual('chr2', ReferenceName('chr1'))
        self.assertTrue(ReferenceName('chr1') == 'chr1')
        self.assertTrue(ReferenceName('chr1') != 'chr2')

    def test_prefixed_vs_naked_str(self):
        self.assertEqual('1', ReferenceName('chr1'))
        self.assertNotEqual('2', ReferenceName('chr1'))
        self.assertTrue(ReferenceName('chr1') == '1')

    def test_obj_comparison(self):
        r = ReferenceName('1')
        rprefix = ReferenceName('chr1')
        r2 = ReferenceName('2')
        r2prefix = ReferenceName('chr2')
        self.assertEqual(r, rprefix)
        self.assertEqual(rprefix, r)
        self.assertEqual(rprefix, ReferenceName('chr1'))
        self.assertEqual(r, ReferenceName('1'))
        self.assertNotEqual(r2, rprefix)
        self.assertNotEqual(r2prefix, rprefix)
        self.assertNotEqual(r2, r)
        self.assertNotEqual(r2prefix, r)
        self.assertTrue(r == rprefix)
        self.assertTrue(r != r2prefix)
        self.assertFalse(r != rprefix)

    def test_lt(self):
        r = ReferenceName('1')
        rprefix = ReferenceName('chr1')
        r2 = ReferenceName('2')
        r2prefix = ReferenceName('chr2')
        self.assertTrue(r <= rprefix)
        self.assertFalse(r < rprefix)
        self.assertFalse(rprefix < r)
        self.assertTrue(rprefix <= r)
        for chr1, chr2 in itertools.product([r, rprefix], [r2, r2prefix]):
            self.assertTrue(chr1 < chr2)
            self.assertTrue(chr1 <= chr2)

    def test_alpha_sort(self):
        self.assertTrue(ReferenceName('10') < ReferenceName('3'))
        self.assertTrue(ReferenceName('10') < ReferenceName('chr3'))
        self.assertTrue(ReferenceName('chr10') < ReferenceName('3'))
        self.assertTrue(ReferenceName('chr10') < ReferenceName('chr3'))

    def test_gt(self):
        r = ReferenceName('1')
        rprefix = ReferenceName('chr1')
        r2 = ReferenceName('2')
        r2prefix = ReferenceName('chr2')
        self.assertTrue(rprefix >= r)
        self.assertTrue(r >= rprefix)
        self.assertFalse(r > rprefix)
        self.assertFalse(rprefix > r)
        for chr1, chr2 in itertools.product([r, rprefix], [r2, r2prefix]):
            self.assertTrue(chr2 > chr1)
            self.assertTrue(chr2 >= chr1)

    def test_hash(self):
        self.assertTrue(ReferenceName('3') in {ReferenceName('3')})
        self.assertTrue(ReferenceName('3') in {ReferenceName('chr3')})


class TestIndelCall(unittest.TestCase):
    def test_duplication_in_repeat(self):
        ref = 'ASFHGHGSFSFSLLLLLL' 'FLLLLSFSLMVPWSFKW'
        mut = 'ASFHGHGSFSFSLLLLLLL' 'FLLLLSFSLMVPWSFKW'

        call = IndelCall(ref, mut)
        print(call)

        self.assertEqual(18, call.nterm_aligned)
        self.assertEqual(len(ref) - 13 + 1, call.cterm_aligned)
        self.assertTrue(call.is_dup)

        self.assertEqual('p.L18dupL', call.hgvs_protein_notation())

    def test_nterminal_extension(self):

        ref = 'MABCDEFGH'
        mut = 'MAFMABCDEFGH'

        call = IndelCall(ref, mut)
        print(call)
        self.assertFalse(call.nterm_aligned)
        self.assertEqual(len(call.ref_seq) - 1 + 1, call.cterm_aligned)
        self.assertFalse(call.is_dup)
        self.assertEqual('MAF', call.ins_seq)
        self.assertEqual('', call.del_seq)

        self.assertEqual('p.M1ext-3', call.hgvs_protein_notation())

    def test_nterminal_deletion(self):
        ref = 'MABCDEFGH'
        mut = 'CDEFGH'

        call = IndelCall(ref, mut)
        print(call)
        self.assertFalse(call.nterm_aligned)
        self.assertEqual(len(call.ref_seq) - 4 + 1, call.cterm_aligned)
        self.assertFalse(call.is_dup)
        self.assertEqual('', call.ins_seq)
        self.assertEqual('MAB', call.del_seq)

        self.assertEqual('p.M1_B3delMAB', call.hgvs_protein_notation())

    def test_cterminal_deletion(self):
        ref = 'MABCDEFGH'
        mut = 'MABCDE'

        call = IndelCall(ref, mut)
        print(call)
        self.assertEqual(6, call.nterm_aligned)
        self.assertFalse(call.cterm_aligned)
        self.assertFalse(call.is_dup)
        self.assertEqual('', call.ins_seq)
        self.assertEqual('FGH', call.del_seq)

        self.assertEqual('p.F7_H9delFGH', call.hgvs_protein_notation())

    def test_cterminal_extension(self):
        ref = 'MABCDEFGH'
        mut = 'MABCDEFGHIJK'

        call = IndelCall(ref, mut)
        print(call)
        self.assertEqual(9, call.nterm_aligned)
        self.assertFalse(call.cterm_aligned)
        self.assertFalse(call.is_dup)
        self.assertEqual('IJK', call.ins_seq)
        self.assertEqual('', call.del_seq)

        self.assertEqual('p.H9ext3', call.hgvs_protein_notation())

    def test_cterminal_stop_extension(self):
        ref = 'MABCDEFGH*'
        mut = 'MABCDEFGHIJK*'

        call = IndelCall(ref, mut)
        print(call)
        self.assertEqual(9, call.nterm_aligned)
        self.assertFalse(call.cterm_aligned)
        self.assertFalse(call.is_dup)
        self.assertEqual('IJK', call.ins_seq)
        self.assertEqual('', call.del_seq)

        self.assertEqual('p.*10ext*3', call.hgvs_protein_notation())

    def test_cterminal_no_orf_ext(self):
        ref = 'MABCDEFGH'
        mut = 'MABCDEFGHIJK*'

        call = IndelCall(ref, mut)
        print(call)
        self.assertEqual(9, call.nterm_aligned)
        self.assertFalse(call.cterm_aligned)
        self.assertFalse(call.is_dup)
        self.assertEqual('IJK*', call.ins_seq)
        self.assertEqual('', call.del_seq)

        self.assertEqual('p.H9ext*4', call.hgvs_protein_notation())

    def test_single_aa_insertion(self):
        ref = 'MABCDEFGH'
        mut = 'MABCKDEFGH'

        call = IndelCall(ref, mut)
        print(call)
        self.assertEqual(4, call.nterm_aligned)
        self.assertEqual(len(call.ref_seq) - 5 + 1, call.cterm_aligned)
        self.assertFalse(call.is_dup)
        self.assertEqual('K', call.ins_seq)
        self.assertEqual('', call.del_seq)

        self.assertEqual('p.C4_D5insK', call.hgvs_protein_notation())

    def test_insertion(self):
        ref = 'MABCDEFGH'
        mut = 'MABCKADEFGH'

        call = IndelCall(ref, mut)
        print(call)
        self.assertEqual(4, call.nterm_aligned)
        self.assertEqual(len(call.ref_seq) - 5 + 1, call.cterm_aligned)
        self.assertFalse(call.is_dup)
        self.assertEqual('KA', call.ins_seq)
        self.assertEqual('', call.del_seq)

        self.assertEqual('p.C4_D5insKA', call.hgvs_protein_notation())

    def test_single_aa_deletion(self):
        ref = 'MABCDEFGH'
        mut = 'MABCEFGH'

        call = IndelCall(ref, mut)
        print(call)
        self.assertEqual(4, call.nterm_aligned)
        self.assertEqual(len(call.ref_seq) - 6 + 1, call.cterm_aligned)
        self.assertFalse(call.is_dup)
        self.assertEqual('', call.ins_seq)
        self.assertEqual('D', call.del_seq)

        self.assertEqual('p.D5delD', call.hgvs_protein_notation())

    def test_deletion(self):
        ref = 'MABCDEFGH'
        mut = 'MABCFGH'

        call = IndelCall(ref, mut)
        print(call)
        self.assertEqual(4, call.nterm_aligned)
        self.assertEqual(len(call.ref_seq) - 7 + 1, call.cterm_aligned)
        self.assertFalse(call.is_dup)
        self.assertEqual('', call.ins_seq)
        self.assertEqual('DE', call.del_seq)

        self.assertEqual('p.D5_E6delDE', call.hgvs_protein_notation())

    def test_deletion_in_repeat(self):
        ref = 'MABCDEEEEEEFGH'
        mut = 'MABCDEEEEFGH'

        call = IndelCall(ref, mut)
        print(call)
        self.assertEqual(9, call.nterm_aligned)
        self.assertEqual(len(call.ref_seq) - 8 + 1, call.cterm_aligned)
        self.assertFalse(call.is_dup)
        self.assertEqual('', call.ins_seq)
        self.assertEqual('EE', call.del_seq)

        self.assertEqual('p.E10_E11delEE', call.hgvs_protein_notation())

    def test_insertion_in_repeat(self):
        ref = 'MABCDEEEEFGH'
        mut = 'MABCDEEEEEEFGH'

        call = IndelCall(ref, mut)
        print(call)
        self.assertEqual(9, call.nterm_aligned)
        self.assertEqual(len(call.ref_seq) - 6 + 1, call.cterm_aligned)
        self.assertTrue(call.is_dup)
        self.assertEqual('EE', call.ins_seq)
        self.assertEqual('', call.del_seq)

        self.assertEqual('p.E8_E9dupEE', call.hgvs_protein_notation())
