""" Dog door code transliterated from McLaughlin, Pollice, and West,
Head First Object-Oriented Analysis & Design, Ch. 2-4"""

from threading import Timer 
from time import sleep

class DogDoor(object):
  def __init__(self):
    self.__open = False
    self.__allowedBarks = list()

  def open(self):
    print "The dog door opens."
    self.__open = True
    # Use a timer and an anonymous function to close the door in 5 seconds.
    # (Note: A function with no parameters is sometimes called a "thunk".)
    t = Timer(5.0, lambda: self.close()) 
    t.start()

  def close(self):
    print "The dog door closes."
    self.__open = False

  def isOpen(self):
    return self.__open

  def addAllowedBark(self, bark):
    if not isinstance(bark, Bark):
      raise TypeError("addAllowedBark only takes Barks.")
    self.__allowedBarks.append(bark)

  def getAllowedBarks(self):
    for i in self.__allowedBarks:
      yield i
       

class Remote(object):
  def __init__(self, door):
    self.door = door

  def pressButton(self):
    print "Pressing the remote control button..."
    if door.isOpen():
      door.close()
    else:
      door.open()

class BarkRecognizer(object):
  def __init__(self, door):
    self.door = door

  def recognize(self, bark):
    print " BarkRecognizer: Heard a %s" % bark.getSound()
    if bark in self.door.getAllowedBarks():
      self.door.open()
      return
    print "This dog is not allowed."
    
class Bark(object):
  def __init__(self, barkSound):
    self.__sound = barkSound

  def getSound(self):
    return self.__sound

  def __eq__(self, otherBark):
    return self.getSound() == otherBark.getSound()

def chapter3Tests():
  door = DogDoor()
  recognizer = BarkRecognizer(door)
  remote = Remote(door)

  # Simulate the hardware hearing a bark
  print "Fido starts barking."
  recognizer.recognize("Woof")
  print "Fido has gone outside..."
  print "Fido's all done..."

  # 10 seconds pass...
  sleep(10.0)
  print "...but he's stuck outside!"

  # Simulate the hardware hearing a bark again.
  print "Fido starts barking."
  recognizer.recognize("Woof")

  print "Fido's back inside..."

def chapter4Tests():
  door = DogDoor()
  door.addAllowedBark(Bark("rowlf"))
  door.addAllowedBark(Bark("rooowlf"))
  door.addAllowedBark(Bark("rawlf"))
  door.addAllowedBark(Bark("woof"))
  recognizer = BarkRecognizer(door)
  remote = Remote(door)

  # Simulate the hardware hearing a bark
  print "Bruce starts barking."
  recognizer.recognize(Bark("rowlf"))
  print ""
  print "Bruce has gone outside..."

  sleep(10.0)

  print ""
  print "Bruce's all done..."
  print "...but he's stuck outside!"

  # Simulate the hardware hearing a bark (not Bruce!)
  smallDogBark = Bark("yip")
  print "A small dog starts barking."
  recognizer.recognize(smallDogBark)

  sleep(5.0)

  #Simulate the hardware hearing a bark again.,
  print "Bruce starts barking."
  recognizer.recognize(Bark("rooowlf"))
  print ""
  print "Bruce's back inside..."
   
if __name__ == '__main__':
  chapter4Tests() # Change to Ch. 4 when you are ready!

