# imports all necessary libraries and sets predetermined values
import RPi.GPIO as GPIO
import time
from apa102_pi.driver import apa102

GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(0)

# de onderstaande pin waardes mogen aangepast worden
register_shift_clock_pin = 17
register_latch_clock_pin = 27
register_data_pin = 22
sensor_trigger_pin = 14
sensor_echo_pin = 15
servo_pin = 14
button_pin = 27

GPIO.setup(register_shift_clock_pin, GPIO.OUT)
GPIO.setup(register_latch_clock_pin, GPIO.OUT)
GPIO.setup(register_data_pin, GPIO.OUT)
GPIO.setup(sensor_trigger_pin, GPIO.OUT)
GPIO.setup(sensor_echo_pin, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
GPIO.setup(servo_pin, GPIO.OUT)
GPIO.setup(button_pin, GPIO.IN)


################################


def set_strip(value):
    strip = apa102.APA102(num_led=8, order='rgb')
    for x in range(8):
        strip.set_pixel_rgb(x, value)
        strip.show()


######################################


def set_register(value):
    """waardes die worden geaccepteerd: 1, 2 ,4, 8, 16, 32, 64, 128"""
    for k in range(0, 8):  # 8 keer loopen
        if value % 2 == 1:  # als waarde oneven is
            GPIO.output(register_data_pin, GPIO.HIGH)  # data pin hoog zetten
        else:  # waarde is even
            GPIO.output(register_data_pin, GPIO.LOW)  # data pin laag houden
        value = value // 2  # waarde halveren

        GPIO.output(register_shift_clock_pin, GPIO.HIGH)  # klok hoog, om de waarde pin te laten aflezen
        GPIO.output(register_shift_clock_pin, GPIO.LOW)  # klok laag, default positie

    GPIO.output(register_latch_clock_pin, GPIO.HIGH)  # geen idee, waarschijnlijk om de waardes op te laten slaan in de chip
    GPIO.output(register_latch_clock_pin, GPIO.LOW)  # default positie
    return True


###############################################


def poll_sensor():
    """
    Return the distance in cm as measured by an SR04
    that is connected to the trig_pin and the echo_pin.
    These pins must have been configured as output and input.s
    """

    GPIO.output(sensor_trigger_pin, False)  # altijd met false starten
    time.sleep(0.5)
    GPIO.output(sensor_trigger_pin, True)
    time.sleep(0.00001)  # pulse trigger
    GPIO.output(sensor_trigger_pin, False)

    while not GPIO.input(sensor_echo_pin):
        start_time = time.time()  # tijd opslaan wanneer de echo false is

    while GPIO.input(sensor_echo_pin):
        end_time = time.time()  # tijd opslaan wanneer de echo true is

    total_time = end_time - start_time  # totaal aantal afstand in seconden
    return (
        round(total_time * 34300 / 2, 2), total_time)  # tuple terug geven met afstand in cm en totaal aantal seconden
    # sensor is niet helemaal naukeurig(~1-2cm variatie), kan ook aan de rpi timing liggen


###########################################


# geef het aantal graden in tussen 0 en 180 (dit is niet hoeveelheid verplaatsing maar naar welke positie)
def set_servo(degrees):
    p = GPIO.PWM(servo_pin, 50)
    p.start(2.5)

    if degrees > 180:
        return False
    elif degrees < 0:
        return False

    left_span = 180 - 0
    right_span = 12 - 2.5

    value_scaled = float(degrees - 0) / float(left_span)

    integer = 2.5 + (value_scaled * right_span)

    p.ChangeDutyCycle(integer)

    return True


###########################################


# Function to check if Switch is pressed, will return a True or False Boolean
def poll_button():
    if GPIO.input(button_pin):
        return True
    else:
        return False