from ..roomEditor import RoomEditor
from ..assembler import ASM
from ..utils import formatText


def removeOwlEvents(rom):
    # Remove all the owl events from the entity tables.
    for room in range(0x100):
        re = RoomEditor(rom, room)
        if re.hasEntity(0x41):
            re.removeEntities(0x41)
            re.store(rom)
    # Clear texts used by the owl. Potentially reused somewhere o else.
    # 1 Used by empty chest (master stalfos message)
    # 8 unused (0x0C0-0x0C7)
    # 1 used by bowwow in chest
    # 1 used by item for other player message
    # 2 used by arrow chest messages
    # 2 used by tunics
    
    # Undoing this, we use it for text shuffle now
    #rom.texts[0x0D9] = b'\xff'  # used by boomerang
    # for idx in range(0x0BE, 0x0CE):
    #     rom.texts[idx] = b'\xff'


    # Patch the owl entity into a ghost to allow refill of powder/bombs/arrows
    rom.texts[0xC0] = formatText("Everybody hates me, so I give away free things in the hope people will love me. Want something?", ask="Okay No")
    rom.texts[0xC1] = formatText("Good for you.")
    rom.patch(0x06, 0x27F5, 0x2A77, ASM("""
    ; Check if we have powder or bombs.
    ld   e, INV_SIZE
    ld   hl, $DB00
loop:
    ldi  a, [hl]
    cp   $02 ; bombs
    jr   z, hasProperItem
    cp   $0C ; powder
    jr   z, hasProperItem
    cp   $05 ; bow
    jr   z, hasProperItem
    dec  e
    jr   nz, loop
    ret
hasProperItem:
    
    ; Render ghost
    ld de, sprite
    call $3BC0

    call $64C6 ; check if game is busy (pops this stack frame if busy)

    ldh a, [$E7] ; frame counter
    swap a
    and  $01
    call $3B0C ; set entity sprite variant
    call $641A ; check collision
    ldh  a, [$F0] ;entity state
    rst 0
    dw  waitForTalk
    dw  talking

waitForTalk:
    call $645D ; check if talked to
    ret  nc
    ld   a, $C0
    call $2385 ; open dialog
    call $3B12 ; increase entity state
    ret

talking:
    ; Check if we are still talking
    ld   a, [$C19F]
    and  a
    ret  nz
    call $3B12 ; increase entity state
    ld   [hl], $00 ; set to state 0
    ld   a, [$C177] ; get which option we selected
    and  a
    ret  nz

    ; Give powder
    ld   a, [$DB4C]
    cp   $20
    jr   nc, doNotGivePowder
    ld   a, $20
    ld   [$DB4C], a
doNotGivePowder:

    ld   a, [$DB4D]
    cp   $30
    jr   nc, doNotGiveBombs
    ld   a, $30
    ld   [$DB4D], a
doNotGiveBombs:

    ld   a, [$DB45]
    cp   $30
    jr   nc, doNotGiveArrows
    ld   a, $30
    ld   [$DB45], a
doNotGiveArrows:

    ld   a, $C1
    call $2385 ; open dialog
    ret

sprite:
    db   $76, $09, $78, $09, $7A, $09, $7C, $09
""", 0x67F5), fill_nop=True)
    rom.patch(0x20, 0x0322 + 0x41 * 2, "734A", "564B")  # Remove the owl init handler

    re = RoomEditor(rom, 0x2A3)
    re.entities.append((7, 6, 0x41))
    re.store(rom)


def upgradeDungeonOwlStatues(rom):
    # Call our custom handler after the check for the stone beak
    rom.patch(0x18, 0x1EA2, ASM("ldh a, [$F7]\ncp $FF\njr nz, $05"), ASM("ld a, $09\nrst 8\nret"), fill_nop=True)

def upgradeOverworldOwlStatues(rom):
    # Replace the code that handles signs/owl statues on the overworld
    # This removes a "have marin with you" special case to make some room for our custom owl handling.
    rom.patch(0x00, 0x201A, ASM("""
        cp   $6F
        jr   z, $2B
        cp   $D4
        jr   z, $27
        ld   a, [$DB73]
        and  a
        jr   z, $08
        ld   a, $78
        call $237C
        jp   $20CF
    """), ASM("""
        cp   $D4
        jr   z, $2B
        cp   $6F
        jr   nz, skip

        ld   a, $09
        rst 8
        jp   $20CF
skip:
    """), fill_nop=True)
