try:
	from tkinter import mainloop
	from time import time
	from threading import Thread
except:
	from Tkinter import mainloop
from compiled_gui import *
PROJECT_DIR = '/usr/local/bin'
class BoardType:
    Rpi4 = 0
    Rpi3 = 1
    PcDuino = 2
    Debug = 3
#INIT_LOGIC
boardType = BoardType.Rpi4

GPIO_MODE_PATH = "/sys/class/gpio/gpio{}/direction"
GPIO_PIN_PATH = "/sys/class/gpio/gpio{}/value"
ADC_PATH = os.path.normpath('/proc')
ADC_FILENAME = 'adc'
PWM_PATH = os.path.normpath('/dev/pwmtimer')
PWM_STOP_TIME_ADDRESS = 0x102
PWM_START_TIME_ADDRESS = 0x101
PWM_FREQ_ADDRESS = 0x107
PWMTMR_FUNC_ADDRESS = 0x103
PWMTMR_TONE_ADDRESS = 0x104
PWM_CONFIG_ADDRESS = 0x105
HWPWM_DUTY_ADDRESS = 0x106
MAX_PWMTIMER_FREQ = 2000
MIN_PWMTIMER_FREQ = 126
GPIO_FILNAME = 'gpio'

# isPcduino = False
# isRaspberryPi = False

if boardType == BoardType.Rpi4 or boardType == BoardType.Rpi3:
    import RPi.GPIO as RPI_GPIO
    RPI_GPIO.setmode(RPI_GPIO.BCM)


class GPIO:
    HIGH = "1"
    LOW = "0"
    INPUT = "in"
    OUTPUT = "out"
    INPUT_PULLUP = "8"
    A0 = 0
    A1 = 1
    A2 = 2
    A3 = 3
    A4 = 4
    A5 = 5

    def __init__(self):
        pass
        # self.pinModeList = [os.path.join(
        #     GPIO_MODE_PATH, 'gpio'+str(idx)) for idx in range(24)]
        # self.pinDataList = [os.path.join(
        #     GPIO_PIN_PATH, 'gpio'+str(idx)) for idx in range(24)]
        # self.adcFiles = [os.path.join(
        #     ADC_PATH, ADC_FILENAME+str(idx)) for idx in range(6)]

    def exportPin(self, pinNumber):
        export_path = "/sys/class/gpio/export"
        with open(export_path, 'r+') as file:
            file.write(pinNumber)

    def pinMode(self, pinNumber, mode):
        print("Initialized pin ", pinNumber)

        if boardType == BoardType.PcDuino:
            pin_path = GPIO_MODE_PATH.format(pinNumber)
            try:
                self.exportPin(pinNumber)
            except:
                print("Pin already exported")
            with open(pin_path, 'r+') as file:
                file.write(mode)
        elif boardType == BoardType.Rpi4:
            RPI_GPIO.setup(int(pinNumber), RPI_GPIO.OUT if mode ==
                           GPIO.OUTPUT else RPI_GPIO.IN)
        else:
            print("Initializing pin: ", pinNumber, " mode: ", mode)

    def digitalWrite(self, pinNumber, state):
        print("Output power", state)
        if boardType == BoardType.PcDuino:
            pin_path = GPIO_PIN_PATH.format(pinNumber)
            with open(pin_path, 'r+') as file:
                file.write(state)
        elif boardType == BoardType.Rpi4:
            RPI_GPIO.output(int(pinNumber), RPI_GPIO.HIGH if state ==
                            GPIO.HIGH else RPI_GPIO.LOW)
        else:
            print("Writing pin: ", pinNumber, " state: ", state)

    def digitalRead(self, pinNumber):
        if boardType == BoardType.PcDuino:
            pin_path = GPIO_PIN_PATH.format(pinNumber)
            with open(pin_path, 'r') as file:
                state = file.read().replace("\n", "").replace(" ", "").replace("\t", "")
            return state
        elif boardType == BoardType.Rpi4:
            pin_path = GPIO_PIN_PATH.format(pinNumber)
            with open(pin_path, 'r') as file:
                state = file.read().replace("\n", "").replace(" ", "").replace("\t", "")
            return 0 if state == GPIO.LOW else 1
        else:
            print("Reading pin: ", pinNumber)

    def setPinFrequency(self, pinNumber, frequency):
        pwm_stop_struct = struct.pack('i', pinNumber)
        pwm_freq_struct = struct.pack('iiiI', pinNumber, 0, 0, frequency)
        if boardType == BoardType.PcDuino:
            with open(PWM_PATH, 'r+') as file:
                if pinNumber in [3, 9, 10, 11]:
                    ioctl(file, PWM_STOP_TIME_ADDRESS, pwm_stop_struct)
                ioctl(file, PWM_FREQ_ADDRESS, pwm_freq_struct)
        else:
            print("Setting frequency pin: ", pinNumber, " to: ", frequency)

    def analogWrite(self, pinNumber, value):
        pwm_config = struct.pack('ii', pinNumber, value)
        pwm_start_struct = struct.pack('i', 0)
        if boardType == BoardType.PcDuino:
            with open(PWM_PATH, 'r+') as file:
                if pinNumber in [3, 9, 10, 11]:
                    ioctl(file, PWM_CONFIG_ADDRESS, pwm_config)
                    ioctl(file, PWM_START_TIME_ADDRESS, pwm_start_struct)
                elif pinNumber in [5, 6]:
                    print("HW PWM {}".format(pinNumber))
                    ioctl(file, HWPWM_DUTY_ADDRESS, pwm_config)
        else:
            print("Writing analog pin: ", pinNumber, " value: ", value)

    def analogRead(self, pinNumber):
        if boardType == BoardType.PcDuino:
            with open(self.adcFiles[pinNumber], 'r') as file:
                value = file.read()
            realVal = int(value.split(":")[1])
            return realVal
        else:
            print("Reading analog pin: ", pinNumber)

#GPIOs
gpio = GPIO()

#Screen2
Screen2 = Screen(218,'screen0',600,450,'#ae3232')
#CheckBox1
CheckBox1 = CompiledCheckBox(Screen2,4,"#1f636f",183,149,130,25,'Unchecked',False)
CheckBox1.display_checkbox('CheckBox1',(0, 0),'Arial',18,'#FFFFFF',False,False,tk.NW,'TopLeft')
import math
import random
from numbers import Number
def text_random_letter(text):
	x = int(random.random() * len(text))
	return text[x]

def first_index(my_list, elem):
	try: index = my_list.index(elem) + 1
	except: index = 0
	return index
def last_index(my_list, elem):
	try: index = len(my_list) - my_list[::-1].index(elem)
	except: index = 0
	return index
def lists_remove_random_item(myList):
	x = int(random.random() * len(myList))
	return myList.pop(x)
def colour_blend(colour1, colour2, ratio):
	r1, r2 = int(colour1[1:3], 16), int(colour2[1:3], 16)
	g1, g2 = int(colour1[3:5], 16), int(colour2[3:5], 16)
	b1, b2 = int(colour1[5:7], 16), int(colour2[5:7], 16)
	ratio = min(1, max(0, ratio))
	r = round(r1 * (1 - ratio) + r2 * ratio)
	g = round(g1 * (1 - ratio) + g2 * ratio)
	b = round(b1 * (1 - ratio) + b2 * ratio)
	return '#%02x%02x%02x' % (r, g, b)
def math_median(myList):
	localList = sorted([e for e in myList if isinstance(e, Number)])
	if not localList: return
	if len(localList) % 2 == 0:
		return (localList[len(localList) // 2 - 1] + localList[len(localList) // 2]) / 2.0
	else:
		return localList[(len(localList) - 1) // 2]
def math_modes(some_list):
	modes = []
  # Using a lists of [item, count] to keep count rather than dict
  # to avoid "unhashable" errors when the counted item is itself a list or dict.
	counts = []
	maxCount = 1
	for item in some_list:
		found = False
		for count in counts:
			if count[0] == item:
				count[1] += 1
				maxCount = max(maxCount, count[1])
				found = True
		if not found:
			counts.append([item, 1])
	for counted_item, item_count in counts:
		if item_count == maxCount:
			modes.append(counted_item)
	return modes
def math_standard_deviation(numbers):
	n = len(numbers)
	if n == 0: return
	mean = float(sum(numbers)) / n
	variance = sum((x - mean) ** 2 for x in numbers) / n
	return math.sqrt(variance)
mainloop()