import time

import RPi.GPIO as GPIO


class LCD:
    wait = 1e-3

    def __init__(self, RS=3, RW=15, E=14, D0=12, D1=16, D2=20, D3=21, D4=23, D5=24, D6=25, D7=8):
        self.RS = RS
        self.RW = RW
        self.E = E
        self.D0 = D0
        self.D1 = D1
        self.D2 = D2
        self.D3 = D3
        self.D4 = D4
        self.D5 = D5
        self.D6 = D6
        self.D7 = D7

    def setup(self):
        DataBits = [self.D0, self.D1, self.D2, self.D3, self.D4, self.D5, self.D6, self.D7]
        GPIO.setwarnings(False)
        GPIO.setmode(GPIO.BCM)
        GPIO.setup(self.RS, GPIO.OUT)
        GPIO.setup(self.RW, GPIO.OUT)
        GPIO.setup(self.E, GPIO.OUT)
        for i in range(8):
            GPIO.setup(DataBits[i], GPIO.OUT)

    def Enable(self):
        GPIO.output(self.E, 1)
        time.sleep(LCD.wait)
        GPIO.output(self.E, 0)
        time.sleep(LCD.wait)

    def reset(self):
        LCD.write4bits(self, int("0011", 2))
        LCD.write4bits(self, int("0011", 2))
        LCD.write4bits(self, int("0011", 2))
        LCD.write4bits(self, int("0010", 2))

    def initLCD4bit(self):
        LCD.reset(self)

        LCD.write4bitsTwice(self, 0x2C, 0)
        LCD.write4bitsTwice(self, 0x0F, 0)
        LCD.write4bitsTwice(self, 0x01, 0)
        LCD.write4bitsTwice(self, 0x06, 0)

    def write4bitsTwice(self, value, rs_mode):
        GPIO.output(self.RS, rs_mode)
        DataBits = [self.D0, self.D1, self.D2, self.D3, self.D4, self.D5, self.D6, self.D7]
        time.sleep(LCD.wait)

        for i in range(4):
            GPIO.output(DataBits[i + 4], 1 if ((value >> i + 4) & 1) > 0
            else 0)
        LCD.Enable(self)
        for i in range(4):
            GPIO.output(DataBits[i + 4], 1 if ((value >> i) & 1) > 0
            else 0)
        LCD.Enable(self)

    def write4bits(self, value):
        GPIO.output(self.RS, 0)
        DataBits = [self.D0, self.D1, self.D2, self.D3, self.D4, self.D5, self.D6, self.D7]
        time.sleep(LCD.wait)

        for i in range(4):
            GPIO.output(DataBits[i + 4], 1 if ((value >> i) & 1) > 0
            else 0)
        LCD.Enable(self)

    def printMsg(self, msg):
        for l in msg:
            LCD.write4bitsTwice(self, ord(l), 1)

    def message(self):
        self.printMsg('Speler 1: €5000')

        self.write4bitsTwice(0xC0, 0)
        self.printMsg("Speler 2: €14000")

        self.write4bitsTwice(0x94, 0)
        self.printMsg('Speler 3: €2200')

        self.write4bitsTwice(0xD4, 0)
        self.printMsg('Speler 4: €1900')

    def __str__(self):
        pass


try:
    run = LCD()
    run.setup()
    run.reset()
    run.initLCD4bit()
    run.message()
    while True:
        pass
except (KeyboardInterrupt, SystemExit):
    destroy = LCD()
    destroy.reset()
    GPIO.cleanup()
