class PassiveManager():
    def __init__(self, composition_runner):
        self.CurrentPassive = Passive()
        self.Timer = SleepingThread(self.ThreadTimerTick, 5)
        self.Timer.start()
        self.runner = composition_runner
        self.LastRun = datetime.datetime.now()
        self.LoadFile()

    def LoadFile(self):
        print "Loading passive "+FileLocation
        if os.path.isfile(FileLocation):
            filePointer = open(FileLocation,"r")
            json_load = json.load(filePointer)
            self.CurrentPassive = Passive(json_load)
            filePointer.close()

    def SaveToFile(self, passive):

        try:
            print "Save passive"
            filePointer = open(FileLocation,"w")
            json_dumps = json.dumps(passive, cls=MyEncoder)
            print json_dumps
            filePointer.write(json_dumps)
            filePointer.flush()
            filePointer.close()
            print "done saving passive"
        except ValueError:
            print "Oops!  That was no valid number.  Try again..."


    def SetCurrentPassive(self, passive):
        print "Setting new passive", passive
        if isinstance(passive, Passive):
            self.CurrentPassive = passive
            self.SaveToFile(passive)

    def ThreadTimerTick(self):
        datetime_now = datetime.datetime.now()
        if datetime_now.hour >= self.CurrentPassive.SleepTime:
            # print "skip because of the hour is less than sleep time"
            return

        if datetime_now.hour < self.CurrentPassive.StartTime:
            # print "skip because of the time is less than start time"
            return

        if  (datetime_now - self.LastRun).total_seconds() > (self.CurrentPassive.Interval*60):
            self.CurrentPassive.LastRun = str(datetime_now)
            self.LastRun = datetime_now
            self.RunRandomSequence()


    def RunRandomSequence(self):
        print "Running a Composition"
        if len(self.CurrentPassive.Compositions) > 0:
            self.runner.AddChoreography(choice(self.CurrentPassive.Compositions))
        else:
            print "no items to choose from"
class CompositionRunner():
    def __init__(self):
        self.Initialize()
        self.StartTheThread()
        self.SetLastComposition = None

    def Initialize(self):
        self.sleepTime = 1
        self.queue = Queue()

    def StartTheThread(self):
        self.Timer = SleepingThread(self.WorkingFunction, 1)
        self.Timer.start()
        print "Starting the running thread"

    def WorkingFunction(self):
        item = self.queue.get()
        print  "Looking at ", item
        try:
            self.RunChoreography(item)
        finally:
            self.queue.task_done()

    def AddChoreography(self, choreography):
        self.queue.put(choreography)

    def RunChoreography(self, item):
        if self.SetLastComposition is not None and item.AllowRepeat:
            self.SetLastComposition(item)
        startTime = datetime.now()
        allDone = False
        while not allDone:
            timedDifference = datetime.now() - startTime
            allDone = True
            for sequence in item.Sequences:
                if isinstance(sequence, Sequences):
                    print "Huh this is not a Sequences", sequence
                try:
                    sequence.Execute(timedDifference.total_seconds() * 1000)
                    allDone = allDone and sequence.Done
                except Exception:
                    print "Exception loading the values", sequence
            time.sleep(0.01)
            # reset to allow another playback

        for sequence in item.Sequences:
            sequence.Done = False

    def SetRepeatComposition(self, setLastComposition):
        self.SetLastComposition = setLastComposition
        pass

    def Stop(self):
        self.Timer.Stop()
        pass
 def __init__(self, composition_runner):
     self.CurrentPassive = Passive()
     self.Timer = SleepingThread(self.ThreadTimerTick, 5)
     self.Timer.start()
     self.runner = composition_runner
     self.LastRun = datetime.datetime.now()
     self.LoadFile()
 def __init__(self, pin, composition_runner,isButtonSwitch):
     self.CurrentPassive = Passive()
     self.Pin = pin
     GPIO.setup(self.Pin, GPIO.IN)
     self.PinValue = GPIO.input(self.Pin)
     self.IsButtonSwitch = isButtonSwitch
     self.Runner = composition_runner
     self.Choreography = []
     self.Choreography.append(Choreography.SimpleSequencesText2Speech(self.GetInitialString()))
     self.CurrentCount = 0
     self.LastCall = datetime.datetime.now()
     self.DelayBeforeReset = datetime.timedelta(0, 60)
     self.Timer = SleepingThread(self.ThreadTimerTick, 0.5)
     self.Timer.start()
class buttonClickRunner():
    def __init__(self, pin, composition_runner,isButtonSwitch):
        self.CurrentPassive = Passive()
        self.Pin = pin
        GPIO.setup(self.Pin, GPIO.IN)
        self.PinValue = GPIO.input(self.Pin)
        self.IsButtonSwitch = isButtonSwitch
        self.Runner = composition_runner
        self.Choreography = []
        self.Choreography.append(Choreography.SimpleSequencesText2Speech(self.GetInitialString()))
        self.CurrentCount = 0
        self.LastCall = datetime.datetime.now()
        self.DelayBeforeReset = datetime.timedelta(0, 60)
        self.Timer = SleepingThread(self.ThreadTimerTick, 0.5)
        self.Timer.start()

    def SetLastComposition(self, lastComposition):
        self.LastComposition = lastComposition
        self.CurrentCount = -1
        self.LastCall = datetime.datetime.now()

    def SetChoreography(self, choreography):
        print "Setting new Choreography for button play", choreography
        self.Choreography = choreography

    def ThreadTimerTick(self):
        if self.IsButtonSwitch:
            if self.PinValue != GPIO.input(self.Pin):
                self.PinValue = GPIO.input(self.Pin)
                self.RunNextSequence()

            else:
                if GPIO.input(self.Pin):
                    self.RunNextSequence()



    def GetNextSequence(self):
        count = len(self.Choreography)
        if datetime.datetime.now() - self.LastCall > self.DelayBeforeReset or self.CurrentCount > (count - 1):
            print "reset"
            self.CurrentCount = 0
        if self.CurrentCount == -1:
            nextSequence = self.LastComposition
        else:
            nextSequence = self.Choreography[self.CurrentCount]
        print "count ", self.CurrentCount
        self.CurrentCount = min(count - 1, self.CurrentCount + 1)
        self.LastCall = datetime.datetime.now()
        return nextSequence

    def RunNextSequence(self):
        sequence = self.GetNextSequence()
        sequence.AllowRepeat = False
        self.Runner.AddChoreography(sequence)

    def GetInitialString(self):
        s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        s.connect(("telkom.co.za", 80))
        myIp = s.getsockname()[0]
        s.close()
        myIp = myIp.replace(".", "dot ")
        myIp = re.sub(r'([1-9])', r'\1 ', myIp)
        return "What is thy bidding, my master? " + myIp
        pass

    def Stop(self):
        self.Timer.Stop()
        pass
 def StartTheThread(self):
     self.Timer = SleepingThread(self.WorkingFunction, 1)
     self.Timer.start()
     print "Starting the running thread"