from patron import Patron
from book import Book
import unittest

class TestPatron(unittest.TestCase):
    def setUp(self):
        self._patron = Patron("Ben Schafer")

    def testGetName(self):
        self.assertEquals("Ben Schafer",self._patron.getName())

    def testGetNumberOfBooksOutInitial(self):
        self.assertEquals(0,self._patron.getNumberOfBooksOut())

    def testCheckOutOne(self):
        self.assert_(self._patron.checkOut())
        self.assertEquals(1,self._patron.getNumberOfBooksOut())

    def testCheckOutTwo(self):
        self._patron.checkOut()
        self._patron.checkOut()
        self.assertEquals(2,self._patron.getNumberOfBooksOut())

    def testCheckOutThree(self):
        self._patron.checkOut()
        self._patron.checkOut()
        self._patron.checkOut()
        self.assertEquals(3,self._patron.getNumberOfBooksOut())

    def testCheckOutFour(self):
        self._patron.checkOut()
        self._patron.checkOut()
        self._patron.checkOut()
        self.assert_(not self._patron.checkOut())
        self.assertEquals(3,self._patron.getNumberOfBooksOut())

    def testCheckInOneExpected(self):
        self._patron.checkOut()
        self.assert_(self._patron.returnBook())
        self.assertEquals(0,self._patron.getNumberOfBooksOut())

    def testCheckInOneUnExpected(self):
        self._patron.checkOut()
        print self._patron
        self._patron.returnBook()
        print self._patron
        self.assert_(not self._patron.returnBook())
        self.assertEquals(0,self._patron.getNumberOfBooksOut())

class TestBook(unittest.TestCase):
    def setUp(self):
        self._book = Book("My Best Seller","Ben Schafer")
        self._b2 = Book("My Sequel","Ben Schafer")
        self._b3 = Book("Some Lame Book","Mark Fienup")
        self._b4 = Book("Omaha","Kevin O'Kane")

    def testBasicAccessors(self):
        self.assertEquals("My Best Seller",self._book.getTitle())
        self.assertEquals("Ben Schafer",self._book.getAuthor())
        self.assertEquals(None,self._book.getPatron())
        print self._book


    def testCleanBorrow(self):
        """One book to one patron"""
        print "One book/one patron"
        p1 = Patron("Ben Schafer")
        self.assertEquals(True,self._book.borrowMe(p1))
        self.assertEquals(p1,self._book.getPatron())
        self.assertEquals("Ben Schafer",self._book.getPatron().getName())

    def testBorrowAlreadyOut(self):
        """Test initial use of waiting list on borrow"""
        print "1 book, two checkouts"
        p1 = Patron("Ben Schafer")
        p2 = Patron("Amy Schafer")
        self.assert_(self._book.borrowMe(p1))
        self.assert_(not self._book.borrowMe(p2))

    def testBorrowOverLimit(self):
        """If the original borrow has three books will the borrow
            prevent the checkout AND allow another patron to check out"""
        print "4 books then 1 to different patron"
        p1 = Patron("Ben Schafer")
        p2 = Patron("Amy Schafer")
        self._book.borrowMe(p1)
        self._b2.borrowMe(p1)
        self._b3.borrowMe(p1)
        #The next borrow should be rejected
        self.assert_(not self._b4.borrowMe(p1))
        #AND, the book should still be accessible to valid patrons
        self.assertEquals(True,self._b4.borrowMe(p2))
        self.assertEquals(p2,self._b4.getPatron())

    def testCleanReturn(self):
        """Does return free up the book"""
        print "1 book, 1 checkout/return, 1 checkout"
        p1 = Patron("Ben Schafer")
        p2 = Patron("Amy Schafer")
        self.assert_(self._book.borrowMe(p1))
        self._book.returnMe()
        self.assertEquals(True,self._book.borrowMe(p2))
        self.assertEquals(p2,self._book.getPatron())


    def testReturnWithWaitinglist(self):
        """Does return with a waiting list COMPLETELY offer it up to someone on list"""
        print "1 book, 2 checkouts, 1return"
        p1 = Patron("Ben Schafer")
        p2 = Patron("Amy Schafer")
        self.assert_(self._book.borrowMe(p1))
        self.assert_(not self._book.borrowMe(p2))
        self.assertEquals(p1,self._book.getPatron())
        self._book.returnMe()
        self.assertEquals(p2,self._book.getPatron())


    def testReturnWithWaitinglistButBookLimit(self):
        """Will the waiting list SKIP the person with three books"""
        print "Will the waiting list SKIP the person with three books"
        p1 = Patron("Ben Schafer")
        p2 = Patron("Amy Schafer")
        p3 = Patron("Harry Mann")
        self._book.borrowMe(p1)
        self._b2.borrowMe(p1)
        self._b3.borrowMe(p1)
        #First, Let Amy get the book
        self.assert_(self._b4.borrowMe(p2))
        #Then, put Ben and Harry on list
        self.assert_(not self._b4.borrowMe(p1))
        self.assert_(not self._b4.borrowMe(p3))
        #Now, return the book and see who gets it (should be Harry)
        self._b4.returnMe()
        self.assertEquals(p3,self._b4.getPatron())
        self.assertEquals(1,p3.getNumberOfBooksOut())
        self.assertEquals(0,p2.getNumberOfBooksOut())
        self.assertEquals(3,p1.getNumberOfBooksOut())


    def testStringPrint(self):
        """What does string look like when checked in and checked out"""
        print "What does string look like when checked in and checked out"
        p1 = Patron("Ben Schafer")
        self.assertEquals(True,self._book.borrowMe(p1))
        print self._book
        self._book.returnMe()
        print self._book


suite = unittest.makeSuite(TestPatron)
unittest.TextTestRunner().run(suite)
suite = unittest.makeSuite(TestBook)
unittest.TextTestRunner().run(suite)    
