import network
import time
import machine
import random
from machine import Pin, ADC, PWM
from umqtt.simple import MQTTClient
import ubinascii # Biblioteca para geração do ID único do cliente MQTT


# Parâmetros para conexão MQTT
MQTT_CLIENT_ID = ubinascii.hexlify(machine.unique_id()) # Gera ID único
MQTT_BROKER    = "broker.mqttdashboard.com"             # Endereço do broker
MQTT_USER      = ""                                     # Usuário (caso possua)
MQTT_PASSWORD  = ""                                     # Senha (caso possua)

# Variável que armazena o nome do tópico que atenderá a requisição
MQTT_TOPIC     = "volume"

# Configuração dos pinos do LED bar graph
led_pins = [23, 22, 21, 19, 25, 26, 27, 14, 12, 13]
leds = []

# Configuração do buzzer
buzzer_pin = Pin(18, Pin.OUT)  # Substitua pelo pino que você está usando para o buzzer
buzzer = PWM(buzzer_pin)


# Função que será chamada quando o ESP receber uma mensagem
def obter_mensagem(topico, mensagem):
    print("\nMensagem recebida: %s" %(mensagem))

    if mensagem == b'tocar C':
        update_leds_for_note("C4")  # Inicializa os LEDs para a nota C4
        time.sleep(1)

    elif mensagem == b'tocar D':
        update_leds_for_note("D4")  # Inicializa os LEDs para a nota D4
        time.sleep(1)

    elif mensagem == b'tocar E':
        update_leds_for_note("E4")  # Inicializa os LEDs para a nota E4
        time.sleep(1)

    elif mensagem == b'tocar F':
        update_leds_for_note("F4")  # Inicializa os LEDs para a nota F4
        time.sleep(1)

    elif mensagem == b'tocar G':
        update_leds_for_note("G4")  # Inicializa os LEDs para a nota G4
        time.sleep(1)

    elif mensagem == b'tocar A':
        update_leds_for_note("A4")  # Inicializa os LEDs para a nota A4
        time.sleep(1)

    elif mensagem == b'tocar B':
        update_leds_for_note("B4")  # Inicializa os LEDs para a nota B4
        time.sleep(1)

    elif mensagem == b'limpar':
        update_leds_for_note("Limpar")  # Inicializa os LEDs para a nota B4
        time.sleep(1)

    elif mensagem == b'tocar musica':
            lista = ['C', 'D', 'E', 'F', 'G', 'A', 'B']
            escolhas_aleatorias = []
            for _ in range(10):
                escolha = random.choice(lista)
                escolhas_aleatorias.append(escolha)
                cliente.publish(MQTT_TOPIC, f"tocar {escolha}")
                #print(f"Nota tocando: ..... {escolha}")
    else:
        print("Mensagem não reconhecida")


# Inicializa os pinos do LED bar graph como saída
for pin_num in led_pins:
    try:
        led_pin = Pin(pin_num, Pin.OUT)
        led_pin.off()  # Garante que o LED esteja inicialmente desligado
        leds.append(led_pin)
    except ValueError:
        print("Erro ao inicializar o pino:", pin_num)

# Inverte a ordem dos LEDs
leds.reverse()


# Frequências das notas musicais e mapeamento de LEDs
note_frequencies = {
    "C4": 261.63,
    "D4": 293.66,
    "E4": 329.63,
    "F4": 349.23,
    "G4": 392.00,
    "A4": 440.00,
    "B4": 493.88
}

note_to_leds = {
    "Limpar": 0,
    "C4": 3,
    "D4": 4,
    "E4": 5,
    "F4": 6,
    "G4": 7,
    "A4": 8,
    "B4": 9
}

notes = list(note_frequencies.keys())

# Função para acender os LEDs com base na nota
def update_leds_for_note(note):
    num_leds_on = note_to_leds[note]
    for i, led_pin in enumerate(leds):
        led_pin.value(1 if i < num_leds_on else 0)  # Ligar ou desligar LED

# Função para tocar uma nota específica e acender os LEDs correspondentes
def play_note_and_update_leds(note):
    frequency = note_frequencies[note]
    buzzer.freq(int(frequency))
    buzzer.duty(512)  # Define a duty cycle para 50%
    update_leds_for_note(note)  # Atualiza os LEDs com base na nota
    time.sleep(0.2)  # Reproduz o som por 0.2 segundos
    buzzer.duty(0)  # Para o som


# Conecta ao WiFi
print("Connectando ao WiFi... ", end="")
estacao = network.WLAN(network.STA_IF)
estacao.active(True)
estacao.connect('Wokwi-GUEST', '')
while not estacao.isconnected():
  pass
print(" Conectado!")

# Conecta ao broker MQTT
print("Connectando ao servidor MQTT... ", end="")
cliente = MQTTClient(MQTT_CLIENT_ID, MQTT_BROKER, user=MQTT_USER, password=MQTT_PASSWORD)
cliente.set_callback(obter_mensagem)
cliente.connect()
cliente.subscribe(MQTT_TOPIC)
print(" Conectado!")
print(f"Tópico conectado: {MQTT_TOPIC}\n")

# Loop principal
try:
    while True:
        # Aguarda mensagens enviadas via MQTT
        cliente.check_msg()  # Verifica se há mensagens MQTT recebidas
        time.sleep(1)
    
    # Caso algum erro aconteça, disconecta do broker e do WiFi
finally:
    cliente.disconnect()
    estacao.disconnect()
    estacao.active(False)
    print("Fim.")
     
    time.sleep(1)