#!/usr/bin/env python

import time, os, random, itertools
from ledcomm import ledComm
from color import ledColor
#import matplotlib
from matplotlib import pyplot
from matplotlib.patches import Circle

class Lighting( ledComm):

    colarr = []

    def __init__(self, num_leds=5, display_plot=True, ledcomm=False):
        self.ledcomm = ledcomm
        self.display_plot = display_plot

        self.colarr = [ ledColor() for i in range(num_leds) ]
        
        if self.ledcomm:
            ledComm.__init__(self)

        if self.display_plot:
            self.init_plot()

        self.update()

    def init_plot(self):
        pyplot.ion()
        pyplot.rc('figure', figsize=(6,6))
        self.fig = pyplot.figure(facecolor=(0.1,0.1,0.1))
        self.ax = self.fig.add_subplot(111)
        self.ax.set_axis_off()

        pyplot.xlim(0,5)
        pyplot.ylim(0,5)

        self.ax.set_axis_bgcolor('black')

        self.patches = [
            Circle((1,1),1,fill=True, color=self.colarr[0].rgb),
            Circle((1,4),1,fill=True, color=self.colarr[2].rgb),
            Circle((4,4),1,fill=True, color=self.colarr[3].rgb),
            Circle((4,1),1,fill=True, color=self.colarr[1].rgb),
            Circle((2.5,2.5),1,fill=True, color=self.colarr[4].rgb)]

        for c in self.patches:
            self.ax.add_patch(c)

        #self.fig.show()
        #pyplot.show()
        pyplot.draw()

    def update_plot(self):
        for i, col in enumerate(self.colarr):
            self.patches[i].set_color( col.rgb)

        #self.fig.show()
        pyplot.draw()

    def update(self):
        if self.ledcomm:
            self.update_leds( *[col.rgb for col in self.colarr])

        if self.display_plot:
            self.update_plot()

            # delay 1/20th second to account for communications delay
            if not self.ledcomm:
                time.sleep(0.05)

    def setcolors(self, *rgbarr):
        for (i, rgbval) in enumerate(rgbarr):
            self.colarr[i].rgb = rgbval
        self.update()

    def test_speed(self, flashes=10):
        gs_full  = [0xFF]*24
        gs_off   = [0x00]*24
        
        for i in range(flashes):
            for c in self.colarr: c.rgb = (1,1,1)
            self.update()

            for c in self.colarr: c.rgb = (0,0,0)
            self.update()
        return

    def strobe(self, flashes=10, on=0.1, off=0.1):
        for i in range(flashes):
            self.toggle(False)
            time.sleep(off)
            self.toggle(True)
            time.sleep(on)

    def test_pattern(self, delay=0.15, cycles=100):
        for i in range(cycles):
            for cols in [ ((1,0,0), (0,1,0), (0,0,1), (1,0,0), (0,0,0)),
                          ((0,0,0), (0,0,0), (0,0,0), (0,0,0), (0,0,0)),
                          ((0,1,0), (0,0,1), (0,1,0), (0,1,0), (0,0,0)),
                          ((0,0,0), (0,0,0), (0,0,0), (0,0,0), (0,0,0)),
                          ((0,0,1), (1,0,0), (0,0,1), (0,0,1), (0,0,0)),
                          ((0,0,0), (0,0,0), (0,0,0), (0,0,0), (0,0,0)),
                          ((0,1,0), (0,1,0), (0,1,1), (1,0,0), (0,0,0)),
                          ((0,0,0), (0,0,0), (0,0,0), (0,0,0), (0,0,0)),
                          ((0,0,1), (0,0,1), (0,0,1), (0,0,1), (0,0,0)),
                          ((0,0,0), (0,0,0), (0,0,0), (0,0,0), (0,0,0))]:
                self.setcolors( cols)
                time.sleep(delay)

    def hue_sweep(self, delay=0, angle_step=0.1, saturation=1, value=1):
        angle = 0.0

        for c in self.colarr[:4]: c.hsv = (0,saturation, value)

        while True:
            angle = (angle + angle_step) % 360

            for led in range(4):
                hue = (angle - led * 90) % 360
                self.colarr[led].set_hue( hue)

            self.update()
            time.sleep(delay)

    def random_hueslew(self, saturation=1, value=1, colspace='rgb', max_steps=20):

        coliters = [ c.slew(hsv=( random.randrange(0,360),saturation,value),
                            max_steps=max_steps,
                            mode='atan', colorspace=colspace)
                     for c in self.colarr]

        while True:
            try:
                for coliter in coliters:
                    # this updates the classes in the color array, so we don't
                    # need the return value
                    coliter.next()
                    
            except StopIteration:
                break
                
            self.update()


    def twinkle(self, delay=0.5, leds=None, white=False, delay_on=0.1, value=1):
        """turn one light on at a time at pre-existing color, or white"""

        if leds is None:
            # first 4 lights
            leds = range(4)

        for led in leds:
            self.colarr[led].set_value(0)
        self.update()

        while True:
            i = random.choice( leds)

            if white:
                self.colarr[i].rgb = (1,1,1)
            else:
                self.colarr[i].set_value(value)

            self.update()
            time.sleep(delay_on)
            
            self.colarr[i].set_value(0)
            self.update()
            time.sleep(delay)

        return


    def twinkle_hue(self, leds=None, saturation=1, value=1,
                          colspace='rgb', steps=20, delay=0):
        if leds is None:
            # first 4 lights
            leds = range(4)

        while True:
            i = random.choice( leds)

            coliter = self.colarr[i].slew( hsv=( random.randrange(0,360),saturation,value),
                                           max_steps=steps,
                                           mode='atan',
                                           colorspace=colspace)
            for col in coliter:
                self.update()

            time.sleep(delay)
            


def test2(on=0.15, off=0.0):
    while True:
        lights.setcolors( (1,0,0), (0,1,0), (0,0,1), (1,0,0), (0,0,0))
        time.sleep(on)
        lights.setcolors( (0,0,0), (0,0,0), (0,0,0), (0,0,0), (0,0,0))
        time.sleep(off)        
        lights.setcolors( (0,1,0), (0,0,1), (0,1,0), (0,1,0), (0,0,0))
        time.sleep(on)
        lights.setcolors( (0,0,0), (0,0,0), (0,0,0), (0,0,0), (0,0,0))
        time.sleep(off)        
        lights.setcolors( (0,0,1), (1,0,0), (0,0,1), (0,0,1), (0,0,0))
        time.sleep(on)
        lights.setcolors( (0,0,0), (0,0,0), (0,0,0), (0,0,0), (0,0,0))
        time.sleep(off)        
        lights.setcolors( (0,1,0), (0,1,0), (0,1,1), (1,0,0), (0,0,0))
        time.sleep(on)
        lights.setcolors( (0,0,0), (0,0,0), (0,0,0), (0,0,0), (0,0,0))
        time.sleep(off) 
        lights.setcolors( (0,0,1), (0,0,1), (0,0,1), (0,0,1), (0,0,0))
        time.sleep(on)
        lights.setcolors( (0,0,0), (0,0,0), (0,0,0), (0,0,0), (0,0,0))
        time.sleep(off)        

def test3(on=0.05):
    r = 1.0
    b = 0.0
    up = True
    while True:
        lights.setcolors( (1,1,1), (r, 0, 1-b), (0, r, b), (0, 1-r, 1-b))
        time.sleep(on)
        if up:
            r = r - 0.001
            b = b + 0.001
            if r <= 0: up=False
        else:
            r = r + 0.001
            b = b - 0.001
            if b <= 0: up=True


def test_flash(off=0.05):
    #beats = os.popen('arecord -r48000 -D copy| vamp-simple-host vamp-example-plugins:percussiononsets:onsets -', 'r')
    beats = os.popen('arecord -r48000 -D copy| vamp-simple-host vamp-aubio:aubioonset:onsets -', 'r')

    #tlc.setcolors( [1,1,1]*4)
    col_on = [1,1,1] * 5
    col_off = [0,0,0] * 5
    col = col_on
    while True:
        beats.readline()
        print "beat!"

        tlc.setcolors( col_off)
        time.sleep(off)
        tlc.setcolors( col_on)

def test_amplitude(off=0.05):
    beats = os.popen('arecord -r48000 -D copy| vamp-simple-host vamp-example-plugins:amplitudefollower -', 'r')

    #tlc.setcolors( [1,1,1]*4)
    col_on = [1,1,1] * 4
    col_off = [0,0,0] * 4
    col = col_on
    while True:
        beats.readline()
        print "beat!"

        tlc.setcolors( col_off)
        time.sleep(off)
        tlc.setcolors( col_on)


if __name__ == "__main__":
    #tlc = tlc5940_fifo()

    lights = Lighting(ledcomm=True, display_plot=False)

    #tlc.senddata( 0x00, gs_full)
    #tlc.senddata( 0x01,dot_full)
    #tlc.set4colors( (1,1,1), (1,1,1), (1,1,1), (1,1,1))
    #tlc.set4colors( (1,0,0), (0,0,0), (0,0,0), (0,0,0))

    
                                                            
    

