import wiringpi
import tty
import itertools
import sys
from time import sleep

class Test(object):
    
    def __init__(self, i2c_addr, base):
        self.i2c_addr = i2c_addr
        self.base = base
        self.pins = range(base, base+16)
        self.init_component()    
        
    def init_component(self):
        wiringpi.mcp23017Setup(self.base, self.i2c_addr)
        for i in self.pins:
            wiringpi.pinMode(i,1)
            wiringpi.digitalWrite(i, 1)
            print(self.pins)
            
    def write(self, pin, value):
        print(str(self.pins[pin]) + "    " + str(value))
        wiringpi.digitalWrite(self.pins[pin], value)

class Test_Display(Test):
    def __init__(self, i2c_addr = 0x21, base = 65 + 16):
        super(Test_Display, self).__init__(i2c_addr, base)
        self.pin_dic = {'d0' : base, 'd1' : base + 1, 'd2' : base + 2, 'bcd0': base + 3, 'bcd1': base + 4, 'bcd2' : base + 5, 'bcd3' : base + 6, 'bcdLT' : base + 7, 'disp1' : base + 8, 'disp2' : base + 9, 'disp3' : base + 10, 'disp4' : base + 11, 'disp5' : base + 12, 'disp6' : base + 13, 'run' : base + 14}
    
    def write_number(self, number):
        print('Writing number: ' + str(number))
        wiringpi.digitalWrite(self.pin_dic['bcd0'], bool(number % 2))
        number = number / 2
        wiringpi.digitalWrite(self.pin_dic['bcd1'], bool(number % 2))
        number = number / 2
        wiringpi.digitalWrite(self.pin_dic['bcd2'], bool(number % 2))
        number = number / 2
        wiringpi.digitalWrite(self.pin_dic['bcd3'], bool(number % 2))
    
    def select_digit(self, digit):
        print('Selecting 7 segment number: ' + str(digit))
        wiringpi.digitalWrite(self.pin_dic['d0'], bool(digit % 2))
        digit = digit / 2
        wiringpi.digitalWrite(self.pin_dic['d1'], bool(digit % 2))
        digit = digit / 2
        wiringpi.digitalWrite(self.pin_dic['d2'], bool(digit % 2))
        
    def disp_select(self, number):
        print('Selecting Display: ' + str(number))
        for i in range(1, 6):
            if(i == number):
              wiringpi.digitalWrite(self.pin_dic['disp' + str(i)], 0)
            else:
              wiringpi.digitalWrite(self.pin_dic['disp' + str(i)], 1)
            #sleep(.1)
            
    def run(self):
        wiringpi.digitalWrite(self.pin_dic['run'], 0)
        #sleep(.001)
        wiringpi.digitalWrite(self.pin_dic['run'], 1)

    def toggleLT(self):
        sleep(.1)
        wiringpi.digitalWrite(self.pin_dic['bcdLT'], 0)
        sleep(.1)
        wiringpi.digitalWrite(self.pin_dic['bcdLT'], 1)
    def clear_disp_select(self):
        print("Clearing Display")
        for i in range(1, 7):
            wiringpi.digitalWrite(self.pin_dic['disp' + str(i)], 1)
      
    def test_digit1(self):
        for i in range(0, 8):
            for j in range(0, 10):
                self.select_digit(i)
                self.clear_disp_select()
                self.write_number(j)
                self.disp_select(1)
                self.run()
    def test(self):
        for k in range(1, 6):
            for i in range(0, 8):
                  self.select_digit(i)
                  for j in range(0, 10):
                      self.write_number(j)
             #         self.toggleLT()
                      self.disp_select(k)
                      self.clear_disp_select()
                      self.run() 
        
    def test123(self):
        self.clear_disp_select()
        self.select_digit(0)
        self.write_number(7)
        wiringpi.digitalWrite(self.pin_dic['run'], 0)
        self.disp_select(1)

    def manual_test(self, display, digit, number):
        self.select_digit(digit)
        self.write_number(number)
        self.disp_select(display)
        self.clear_disp_select()
        self.run()
    def test_digits(self):
        tty.setcbreak(sys.stdin.fileno())
        self.write_number(3)
        for i in range(0,8):
            self.select_digit(i)
            self.disp_select(0)
            self.run()
            sleep(.5)
    def permutation_test(self):
        self.select_digit(3)
        self.write_number(0)
        functions = [self.disp_select, self.clear_disp_select, self.run, self.toggleLT]
        i = 0
        for permutation in itertools.permutations(functions, 4):
            print(str(i))
            for function in permutation:
                function(3)
            print(permutation)
            i = i+1  
            raw_input() 

class Sound_Test(Test):
    def __init__(self, i2c_addr = 0x22, base = 65):
        super(Sound_Test, self).__init__(i2c_addr, base)
        self.pins = [x + base for x in [15, 14, 12, 10, 8, 9, 11, 13]]
        
    def fire(self):
        self.write(7, 0)
        
        
    def stop(self):
        self.write(7, 1)
    
    def init_component(self):
        super(Sound_Test, self).init_component()
        wiringpi.digitalWrite(self.base + 12, 1)
    
    def fire_sound(self, i):
        self.write(0, bool(i & 0b00000001))
        self.write(1, bool(i & 0b00000010))
        self.write(2, bool(i & 0b00000100))
        self.write(3, bool(i & 0b00001000))
        self.write(4, bool(i & 0b00010000))
        self.write(5, bool(i & 0b00100000))
        self.write(6, bool(i & 0b01000000))
        self.write(7, bool(i & 0b10000000))
        self.fire()
        a = raw_input()
        self.stop()

    def rotate(self):
        for i in range(22, 78):
            self.fire_sound(i)

    """
    def init_flipper(self):
        init_driver()
        init_display()
        init_sound()
        
    def init_driver(self):
        i2c_driver = 0x20
        base_driver = 65
        wiringpi.mcp23017Setup(base_driver, i2c_driver)
        
    def init_display(self):
        i2c_display= 0x21
        base_display = 65 + 16
        wiringpi.mcp23017Setup(base_display, i2c_display)
        for i in range(base_display, base_display+16):
            wiringpi.pinMode(i,1)
            wiringpi.digitalWrite(i, 0)
        
    def init_sound(self):
        i2c_sound = 0x22
        base_sound = 65 + 32
        wiringpi.mcp23017Setup(base_sound, i2c_sound)
        for i in range(base_sound, base_sound+16):
            wiringpi.pinMode(i,1)
            wiringpi.digitalWrite(i, 0)
        # set fire to 1 (out)

    def """
