import bl00mbox

blm = bl00mbox.Channel("Melodic Demo")

import leds

from st3m.goose import List, Optional
from st3m.input import InputState, InputController
from st3m.ui.view import ViewManager
from ctx import Context

octave = 0
synths: List[bl00mbox.patches.tinysynth] = []
scale = [0, 2, 4, 5, 7, 9, 11]


def highlight_bottom_petal(num: int, r: int, g: int, b: int) -> None:
    start = 4 + 8 * num
    for i in range(7):
        leds.set_rgb(((i + start) % 40), r, g, b)


def change_playing_field_color(r: int, g: int, b: int) -> None:
    highlight_bottom_petal(0, r, g, b)
    highlight_bottom_petal(1, r, g, b)
    highlight_bottom_petal(3, r, g, b)
    highlight_bottom_petal(4, r, g, b)
    highlight_bottom_petal(2, 55, 0, 55)
    leds.set_rgb(18, 55, 0, 55)
    leds.set_rgb(19, 55, 0, 55)
    leds.set_rgb(27, 55, 0, 55)
    leds.set_rgb(28, 55, 0, 55)
    leds.update()


def adjust_playing_field_to_octave() -> None:
    global octave
    if octave == -1:
        change_playing_field_color(0, 0, 55)
    elif octave == 0:
        change_playing_field_color(0, 27, 27)
    elif octave == 1:
        change_playing_field_color(0, 55, 0)


def run(input: InputController) -> None:
    global scale
    global octave
    global synths
    any_down = False
    for i in range(10):
        petal = input.captouch.petals[i].whole
        if petal.down:
            any_down = True
        if petal.pressed:
            any_down = True
            if i == 6:
                octave = -1
                adjust_playing_field_to_octave()
            elif i == 5:
                octave = 0
                adjust_playing_field_to_octave()
            elif i == 4:
                octave = 1
                adjust_playing_field_to_octave()
            else:
                k = 10 - i
                if k > 3:
                    k -= 10
                k = 3 - k
                note = scale[k] + 12 * octave
                synths[0].signals.pitch.tone = note
                synths[0].signals.trigger.start()

    if not any_down:
        synths[0].signals.trigger.stop()


def init() -> None:
    global synths
    for i in range(1):
        synth = blm.new(bl00mbox.patches.tinysynth)
        synth.signals.output = blm.mixer
        synths += [synth]
    for synth in synths:
        synth.signals.decay = 100


def foreground() -> None:
    adjust_playing_field_to_octave()


from st3m.application import Application, ApplicationContext


# TODO(q3k): properly port this app
class MelodicApp(Application):
    def __init__(self, app_ctx: ApplicationContext) -> None:
        super().__init__(app_ctx)
        init()

    def draw(self, ctx: Context) -> None:
        ctx.rgb(1, 1, 1).rectangle(-120, -120, 240, 240).fill()
        ctx.rgb(0, 0, 0)
        ctx.scope()
        ctx.fill()

    def on_enter(self, vm: Optional[ViewManager]) -> None:
        super().on_enter(vm)
        foreground()

    def think(self, ins: InputState, delta_ms: int) -> None:
        super().think(ins, delta_ms)
        run(self.input)