from RPi import GPIO as g
import time


class Display:
    def __init__(self, datapins, register_select, enable):
        self.__datapins = datapins
        self.__rs = register_select
        self.__enable = enable
        self.__other = ""
        self.setup()

    def setup(self):
        g.setmode(g.BCM)
        for pin in self.__datapins:
            g.setup(pin, g.OUT)
        g.setup(self.__rs, g.OUT)
        g.setup(self.__enable, g.OUT)
        self.__send_instruction(0x3c)
        time.sleep(0.05)
        self.__send_instruction(0x0c)
        time.sleep(0.05)
        self.__send_instruction(0x01)

    def __set_data_bits(self, bits):
        mask = 0x80
        for i, pin in enumerate(self.__datapins):
            if bits & mask >> i == 0:
                g.output(pin, 0)
            else:
                g.output(pin, 1)

    def __send_instruction(self, instructie):
        g.output(self.__rs, 0)
        g.output(self.__enable, 1)
        self.__set_data_bits(instructie)
        time.sleep(0.05)
        g.output(self.__enable, 0)

    def __send_character(self, character):
        # if cursor_position:
        #     if cursor_position < 16:
        #         self.__send_instruction(cursor_position | 0x80)
        #     else:
        #         self.__send_instruction(cursor_position | 0xc0)
        #         print("new line")
        g.output(self.__rs, 1)
        g.output(self.__enable, 1)
        self.__set_data_bits(ord(character))
        time.sleep(0.05)
        g.output(self.__enable, 0)

    def write_message(self, messsage):
        self.__send_instruction(0x1)
        if len(messsage) > 16:
            for letter in messsage[:15]:
                self.__send_character(letter)
            self.second_row()
            for letter in messsage[16:]:
                self.__send_character(letter)
        else:
            for letter in messsage:
                self.__send_character(letter)

    def write_difference(self, value):
        for i in range(0, len(value)):
            if i < len(self.__other):
                if value[i] != self.__other[i]:
                    self.__send_instruction(i | 0x80)
                    self.__send_character(value[i])
            else:
                self.__send_instruction(i | 0x80)
                self.__send_character(value[i], i)
        self.__other = value

    def write_difference_second_row(self, value):
        for i in range(0, len(value)):
            if i < len(self.__other):
                if value[i] != self.__other[i]:
                    self.__send_instruction(i | 0xc0)
                    self.__send_character(value[i])
            else:
                self.__send_instruction(i | 0xc0)
                self.__send_character(value[i])
        self.__other = value

    def stop(self):
        g.cleanup()

    def displayOn(self):
        self.__display_status = not self.__display_status
        if self.__display_status:
            self.__send_instruction(0x8)
        else:
            self.__send_instruction(0x0f)

    def second_row(self):
        self.__send_instruction(0xc0)

    def clear_LCD(self):
        self.__send_instruction(0x1)

    def __del__(self):
        g.cleanup()