import unittest
from bz.conditional import *
from bz.tasks import *


class TestConditional(unittest.TestCase):
    def test_if(self):
        def fn():
            return "success"
        cond = True
        conditional_task = if_(lambda: cond).do(task(fn))
        result = conditional_task.run()
        self.assertEqual("success", result)
        cond = False
        result = conditional_task.run()
        self.assertTrue(result.is_failure())

    def test_if_with_condition_parameters(self):
        def fn():
            return "foo"

        def fn2():
            return "bar"
        conditional_task = if_(lambda prev: prev == "foo").do(task(fn2))
        composite_task = task(fn).then(conditional_task)
        result = composite_task.run()
        self.assertEqual("bar", result)

        def fn3():
            return "not foo"
        composite_task_2 = task(fn3).then(conditional_task)
        result = composite_task_2.run()
        self.assertTrue(result.is_failure())

    def test_if_with_task_parameters(self):
        def fn():
            return "foo"

        def fn2(prev):
            return "the result of the first function was %s" % prev
        conditional_task = if_(lambda prev: prev == "foo").do(task(fn2))
        composite_task = task(fn).then(conditional_task)
        result = composite_task.run()
        self.assertEqual("the result of the first function was foo", result)

    def test_if_with_else(self):
        cond = True

        def fn():
            return "foo"

        def fn2():
            return "bar"
        conditional_task = if_(lambda: cond).do(task(fn), _else=task(fn2))
        result = conditional_task.run()
        self.assertEqual("foo", result)
        cond = False
        result = conditional_task.run()
        self.assertEqual("bar", result)

    def test_if_with_else_parameters(self):
        def fn():
            return "bar"

        def fn2():
            return "success!"

        def fn3(prev):
            return "we wanted 'foo', but we got '%s'" % prev
        conditional_task = if_(lambda prev: prev == "foo").do(task(fn2), _else=task(fn3))
        composite_task = task(fn).then(conditional_task)
        result = composite_task.run()
        self.assertEqual("we wanted 'foo', but we got 'bar'", result)

    def test_if_not(self):
        def fn():
            return "success"
        cond = True
        conditional_task = if_(not_(lambda: cond)).do(task(fn))
        result = conditional_task.run()
        self.assertTrue(result.is_failure())
        cond = False
        result = conditional_task.run()
        self.assertEqual("success", result)

    def test_double_not(self):
        def fn():
            return "success"
        cond = True
        conditional_task = if_(not_(not_(lambda: cond))).do(task(fn))
        result = conditional_task.run()
        self.assertEqual("success", result)
        cond = False
        result = conditional_task.run()
        self.assertTrue(result.is_failure())

    def test_or(self):
        def fn():
            return "success"
        a = b = True
        conditional_task = if_(lambda: a).or_(lambda: b).do(task(fn))
        result = conditional_task.run()
        self.assertEqual("success", result)
        a = False
        result = conditional_task.run()
        self.assertEqual("success", result)
        b = False
        result = conditional_task.run()
        self.assertTrue(result.is_failure())
        a = True
        result = conditional_task.run()
        self.assertEqual("success", result)

    def test_and(self):
        def fn():
            return "success"
        a = b = True
        conditional_task = if_(lambda: a).and_(lambda: b).do(task(fn))
        result = conditional_task.run()
        self.assertEqual("success", result)
        a = False
        result = conditional_task.run()
        self.assertTrue(result.is_failure())
        b = False
        result = conditional_task.run()
        self.assertTrue(result.is_failure())
        a = True
        result = conditional_task.run()
        self.assertTrue(result.is_failure())

    def test_ifbuilder_not(self):
        def fn():
            return "success"
        cond = False
        conditional_task = if_(lambda: cond).not_().do(task(fn))
        result = conditional_task.run()
        self.assertEqual("success", result)
        cond = True
        result = conditional_task.run()
        self.assertTrue(result.is_failure())
