#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Copyright (c) 2017-18 Richard Hull and contributors
# See LICENSE.rst for details.

import re
import time
import argparse

import RPi.GPIO as GPIO

from luma.led_matrix.device import max7219
from luma.core.interface.serial import spi, noop
from luma.core.render import canvas
from luma.core.virtual import viewport
from luma.core.legacy import text, show_message
from luma.core.legacy.font import proportional, CP437_FONT, TINY_FONT, SINCLAIR_FONT, LCD_FONT

from pidigits import piGenerator

class Drip:
    def __init__(self):
        # re-order the following pins according to how you've ordered the LEDs under the spigot
        self.dripPins = [17, 27, 22]
        GPIO.setmode(GPIO.BCM)
        for pin in self.dripPins:
            GPIO.setup(pin, GPIO.OUT)
            GPIO.output(pin, False)
        self.index = -1

    def showNext(self):
        GPIO.output(self.dripPins[self.index], False)
        self.index += 1
        if 0 <= self.index < len(self.dripPins):
            GPIO.output(self.dripPins[self.index], True)
        else:
            self.index = -1

    def reset(self):
        for pin in self.dripPins:
            GPIO.output(pin, False)
        self.index = -1

class ValvePot:
    def __init__(self):
        # Try swapping these pins if reading of potentiometer doesn't seem to work
        self.pinA = 18
        self.pinB = 23

    def discharge(self):
        GPIO.setup(self.pinA, GPIO.IN)
        GPIO.setup(self.pinB, GPIO.OUT)
        GPIO.output(self.pinB, False)
        time.sleep(0.01)

    def chargeTime(self):
        GPIO.setup(self.pinB, GPIO.IN)
        GPIO.setup(self.pinA, GPIO.OUT)
        start = time.time()
        GPIO.output(self.pinA, True)
        while not GPIO.input(self.pinB):
            time.sleep(0.0001)
        elapsed = time.time() - start
        GPIO.setup(self.pinA, GPIO.IN)
        GPIO.setup(self.pinB, GPIO.OUT)
        GPIO.output(self.pinB, False)
        return elapsed

    def analogRead(self):
        self.discharge()
        return int(self.chargeTime() * 10000)

        
nDigits = 5

serial = spi(port=0, device=0, gpio=noop())
device = max7219(serial, cascaded=nDigits, block_orientation=90,
                     rotate=0, blocks_arranged_in_reverse_order=True)

# start message
def startMessage():
    msg = "#PiDay"
    show_message(device, msg, fill="white", font=proportional(CP437_FONT))

drip = Drip()
spigotValve = ValvePot()


startMessage()

piGen = piGenerator()
digitWindow = " " * nDigits
nPiDigits = 0
try:
    while True:

        virtual = viewport(device, width=device.width + 8, height=8)
        with canvas(virtual) as draw:
            for i in range(nDigits):
                text(draw, (i*8, 0), digitWindow[i], fill="white", font=CP437_FONT)


        if nPiDigits != 1 or nextDigit == ".":
            nextDigit = "{}".format(next(piGen))
            nPiDigits += 1
        else:
            nextDigit =  "."

        resetCount = 5
        while resetCount > 0:
            valvePos = spigotValve.analogRead()
            
            # You may need to change the threshold and the direction of the comparison according to how you've wired the 10k potentiometer
            if valvePos < 10:
                break
            if valvePos > 19:
                # reset
                resetCount -= 1
                
            time.sleep(0.5)
            if nPiDigits == 1 and nextDigit != ".":
                startMessage()
                time.sleep(1)

        if resetCount == 0:
            piGen = piGenerator()
            digitWindow = " " * nDigits
            nextDigit = ""
            nPiDigits = 0
            show_message(device, "Reset", fill="white", font=proportional(CP437_FONT))
            continue

            
        for i in range(8):
            if i % 3 == 0 and nextDigit != ".":
                drip.showNext()
            virtual.set_position((i, 0))
            time.sleep(0.125)
        drip.reset()

        digitWindow = digitWindow[1:] + nextDigit 

        if nextDigit != ".":
            x = nDigits * 8
            for r in [3, 2, 1]:
            
                with canvas(virtual) as draw:
                    text(draw, (8, 0), digitWindow, fill="white", font=CP437_FONT)
                    for j in range(0, r):
                        draw.rectangle((x+j, j, x+7-j, 7-j), outline = "black")
                time.sleep(0.05)
        


except KeyboardInterrupt:
    print("Halted")
finally:
    GPIO.cleanup()
