import sys, os, random
import unittest
import tempfile
from operator import itemgetter
from functools import partial

try:
    sys.path.insert(0, os.path.dirname(os.path.dirname(__file__)))
except:
    sys.path.insert(0, os.path.dirname(os.path.abspath(".")))

from bedops import bedmap, overlap_as_array
from . import parseBED

class TestBEDMAP(unittest.TestCase):
    def setUp(self):
        if not ( hasattr(self, "anchor_fn") and os.path.exists(self.anchor_fn) ):
            with tempfile.NamedTemporaryFile(delete=False) as rfd:
                rfd.write("\n".join( ("chr1\t10\t100\ta1\t1.3\t+",
                        "chr1\t200\t290\ta2\t22.2\t+",
                        "chr4\t5\t95\ta3\t43.5\t-\n") ))
                self.anchors = rfd.name

        if not ( hasattr(self, "t1") and os.path.exists(self.t1) ):
            with tempfile.NamedTemporaryFile(delete=False) as mfd:
                mfd.write("\n".join( ("chr1\t15\t30\tt11\t1",
                        "chr1\t25\t30\tmp2\t0.5",
                        "chr3\t55\t80\tmp2\t1",
                        "chr4\t20\t56\tmp3\t23.3\n") ))
                self.t1 = mfd.name
        self.anchor_len = 90
        self.B = random.choice((1, 2, 3, 5, 6, 9))
        self.B = 5

    def test_bedmap(self):
        original_anchors = map(parseBED, open(self.anchors))
        bdemp_res = list( bedmap(self.anchors, self.t1, onlyOverlapping=False) )

        self.assertTrue( all( map(lambda a: a[2]-a[1] == self.anchor_len, original_anchors) ) )
        self.assertEqual( original_anchors, map(parseBED, map(itemgetter(0), bdemp_res)) )

        for anchor_str, ft_str in bdemp_res:
            anchor = parseBED(anchor_str)
            ft_lst = map(parseBED, filter(bool, ft_str.split(";")))

            #all fatures it into anchor
            self.assertTrue( all( map(lambda ft: max(ft[1], anchor[1]) < min(ft[2], anchor[2]), ft_lst) ) )

            x_s = overlap_as_array(anchor, ft_str.split(";"), bin=self.B, parseFeature=partial(parseBED, use_score=True))
            x_c = overlap_as_array(anchor, ft_str.split(";"), bin=self.B, parseFeature=partial(parseBED, use_score=False))

            #print anchor
            #print self.B
            print x_c
            #print x_s
            if anchor[5] == "-":
                print ft_lst
                ft_lst = map(lambda (_ch, _s, _e, _n, _sc): (_ch, anchor[1]+anchor[2]-_e, anchor[2]+anchor[1]-_s, _n, _sc), ft_lst)
                print ft_lst
                print

            self.assertEqual( x_s.shape[0], x_c.shape[0] )
            for i in range(x_c.shape[0]):
                s = anchor[1] + self.B*i
                e = anchor[1] + self.B*(i+1)

                sel_feats = filter(lambda f: max(s, f[1]) < min(e, f[2]), ft_lst)
                overlap = map(lambda f: min(e, f[2]) - max(s, f[1]), sel_feats)
                if anchor[5] == "-":
                    print i, s, e, sel_feats, overlap
                score = map(itemgetter(4), sel_feats)


                self.assertEqual( sum(overlap), x_c[i] )
                self.assertAlmostEqual( x_s[i], sum( map(lambda (s,o): s*o, zip(score, overlap)) ), places=4 )




if __name__ == '__main__':
    unittest.main()

