from machine import Pin, I2C
from i2c_lcd import I2cLcd
from rotary import Rotary
from utime import ticks_ms, sleep_ms
import gc 
from screens import Lcd_Screens
from funcs import wifi_connect, clamp

#############################################################################
# setups e funções

selection = Rotary(5, 17, 16)
cx, cy = 0, 0 # cursor

bufferDict = {"ganhos": [[0,0,0,0], [0,0,0,0], [0,0,0,0]],
              "setpoint": [1,3,5], "voltar": False} # ganho, sp

values = {"ganhos": {"kp": 0.0, 'ki': 0.0, 'kd': 0.0},
		  "setpoint": 135, "modo": "offline"}

state = "none"

lcd = I2cLcd(I2C(0), 0x27, 4, 20) 

def rotary_changed(change): # máquina de estados

	print(change)

	global tela, state, block, lcd, values, cx, cy

	print(bufferDict["voltar"])

	if tela.name == "setpoint":
		cursor_tuples = (10, 11, 12)
		cy = 2

		buff = bufferDict['setpoint']

		if change == Rotary.ROT_CW:
			buff[cx] = (buff[cx] + 1) % 10
		
		elif change == Rotary.ROT_CCW:
			buff[cx] -= 1

		elif change == Rotary.SW_PRESS:
			state = "init"
			return

		elif change == Rotary.SW_RELEASE:
			state = "none"
			if tela.block: return
			cx = (cx +1) % len(cursor_tuples)
			lcd.move_to(cursor_tuples[cx], 0)
			return

		if cx == 0:
			buff[cx] = clamp(buff[cx], 2)

			if buff[0] == 2 and buff[1] > 7:
				lcd.hide_cursor()
				lcd.move_to(11,0)
				lcd.overwrite("7")
				if buff[2] > 0:
					lcd.move_to(12, 0)
					lcd.overwrite("0")
				buff[1] = 7
				buff[2] = 0
				lcd.move_to(10,0)
				lcd.show_cursor()

		elif cx == 1:
			if buff[0] == 2:
				buff[cx] = clamp(buff[cx], 7)

				if buff[cx] == 7 and buff[2] > 0:
					lcd.hide_cursor()
					lcd.move_to(12,0)
					lcd.overwrite("0")
					lcd.move_to(11,0)
					lcd.show_cursor()
					buff[2] = 0
			else:
				buff[cx] = clamp(buff[cx], 9)

		elif cx == 2:
			if buff[0] == 2 and buff[1] == 7:
				buff[2] = 0
			else:
				buff[cx] = clamp(buff[cx], 9)

		bufferDict['setpoint'] = buff

		values[tela.name] = ''.join((str(i) for i in bufferDict[tela.name]))
		print(values[tela.name])

		if tela.block == False:
			lcd.overwrite(str(buff[cx]))

	elif tela.name == "modo_on_offline":
		cursor_tuple = (1, 11)

		cy = 2

		if change == Rotary.ROT_CW:
			cx += 1
		
		elif change == Rotary.ROT_CCW:
			cx -= 1

		elif change == Rotary.SW_PRESS:
			state = "init"

		elif change == Rotary.SW_RELEASE:
			state = "none"

		cx = clamp(cx, 1)

		if cx: values["modo"] = "online"
		else: values["modo"] = "offline"

		if tela.block == False:
			lcd.hide_cursor()
			lcd.overwrite(' ')
			lcd.move_to(cursor_tuple[cx], cy)
			lcd.overwrite("~")
	
	elif tela.name == "online":

		if change == Rotary.SW_PRESS:
			state = "init"

		elif change == Rotary.SW_RELEASE:
			state = "none"

	elif tela.name == "offline":
		# 9, 10, 12, 13

		cursor_tuple = (4,5,7,8,12)
		buff = bufferDict['ganhos']

		if change == Rotary.ROT_CW:
			buff[cy][cx] = clamp(buff[cy][cx] + 1, 9)
			print("oi")
		
		elif change == Rotary.ROT_CCW:
			buff[cy][cx] = clamp(buff[cy][cx] - 1, 9)

		elif change == Rotary.SW_PRESS:
			state = "init"

			if cx == 4:
				bufferDict['voltar'] = True

		elif change == Rotary.SW_RELEASE:
			state = "none"
			if tela.block: return
			cx += 1

			if cy == 2:
				if cx > 4: cy +=1
				cx %= 5
				cy %= 3
			
			else:
				if cx > 3: cy +=1
				cx %= 4
				cy %= 3

			bufferDict['voltar'] = False

		

		if not tela.block:
			lcd.hide_cursor()
			lcd.move_to(cursor_tuple[cx], cy+1)
			if cx == 0 and cy == 0:
				lcd.move_to(12, 3)
				lcd.overwrite(' ')
				lcd.move_to(4, 1)
			elif cy != 2 or cx != 4:
				lcd.overwrite(str(buff[cy][cx]))
			else: lcd.overwrite('~')
			lcd.show_cursor()

	gc.collect()
	print(state)

selection.add_handler(rotary_changed) # passa o callback para o objeto do encoder

tela = Lcd_Screens(lcd) # envia o objeo do lcd para a classe mestre de telas
tela.setpoint()

# wifi = wifi_connect("Wokwi-GUEST", "")
# print(wifi.scan())

# print(tela.name)

#############################################################################
# loop principal e máquina de estados

print("________________________________________________")

state = False

delay = 0
while True:
	if state == "init":
		delay = ticks_ms() + 3000
		state = "countdown"
	
	if ticks_ms() < delay:
		continue

	if state != "countdown": 
		continue

	state = "none"
	delay = 0
	cx, cy = 0, 0
	if tela.name == "modo_on_offline":
		if values["modo"] == "online":
			tela.selecao_wifi()
		else:
			tela.offline()

	elif tela.name == "online":
		values["modo"] = "offline"
		tela.modo_on_offline()

	elif tela.name == "offline":
		valores = values['ganhos']
		if bufferDict['voltar']:
			valores["kp"] = 0
			bufferDict["kp"] = [0]*4
			valores["kI"] = 0
			bufferDict["ki"] = [0]*4
			valores["kd"] = 0
			bufferDict["kd"] = [0]*4
			bufferDict["voltar"] = False
			tela.modo_on_offline()
			continue
		valores['kp'] = float(''.join(str(i) for i in bufferDict['ganhos'][0])) / 100
		valores['ki'] = float(''.join(str(i) for i in bufferDict['ganhos'][1])) / 100
		valores['kd'] = float(''.join(str(i) for i in bufferDict['ganhos'][2])) / 100
		print(valores['kp'], valores['ki'], valores['kd'])

		tela.setpoint()
		
	elif tela.name == "ganho":
		values[tela.name] = ''.join((str(i) for i in bufferDict[tela]))
		print(values[tela])
		tela = lcd_screens("setpoint")

	elif tela.name == "setpoint":
		bufferDict['setpoint'] = [1,3,5]
		values['setpoint'] = 135
		for i in range(3):
			bufferDict['ganhos'][i] = [0]*3

		# values["ganhos"]["kp"] = 0.0
		# values["ganhos"]["ki"] = 0.0
		# values["ganhos"]["kd"] = 0.0

		for i in list(values["ganhos"].keys()):
			values["ganhos"][i] = 0.0

		print(values['ganhos'])
		tela.offline()


	cx, cy = 0, 0

	gc.collect()