PUSHS UNION "Screen Variables", WRAM0[SCREEN_VARS_START]
vAnimationFrame: db ;def vAnimationFrame EQU SCREEN_VARS_START
vState: db ;def vState EQU vAnimationFrame+1
vCurrentAnimation: dw ;def vCurrentAnimation EQU vState+1 ; 2 bytes
vShuffleIndex: db ;def vShuffleIndex equ vCurrentAnimation+2
vShuffleTime: dw ;def vShuffleTime equ vShuffleIndex+1 ; 2 bytes
POPS

def S_Center = 0
def S_RightOut = 1
def S_Right = 2
def S_RightIn = 3
def S_LeftOut = 4
def S_Left = 5
def S_LeftIn = 6
def S_UpOut = 7
def S_Up = 8
def S_UpIn = 9
def S_DownOut = 10
def S_Down = 11
def S_DownIn = 12

ScreenShuffle:
  dw ShuffleSetup
  dw ShuffleUpdate
  dw ShuffleDraw
  dw ShuffleTeardown

ShuffleSetup:
  ld hl, SHUFFLED_DECK
  ld a, [hl]
  dec a
  ld [vShuffleIndex], a 
  
  ld a, 0 
  ld [vAnimationFrame], a 
  
  ld a, S_Center
  ld [vState], a 
  
  ld hl, .asyncTask
  call Async_Spawn_HL
  
  ld hl, ZEROES
  ld de, MY_OAM
  ld bc, $100
  call CopyRange
  ret 
.asyncTask
  ld hl, ONES ; origin
  ld de, _SCRN0 ; destination
  ld b, 18 ; height
  ld c, 20 ; width
  call CopyTilesToMap
  
  ld hl, Shuffle.BigCard
  ld de, _SCRN0 + 32*5 + 8
  ld b, 8
  ld c, 4
  call CopyTilesToMap
  
  ld hl, Shuffle.UITileData
  ld de, _VRAM + $1000 + VARIABLE_TILES_START*16
  ld bc, Shuffle.UITileDataEnd - Shuffle.UITileData
  call CopyRange
  
  ret
  
ShuffleUpdate:
  ; incrrement vShuffleTime so we can use it for seeding RNG
  ld hl, vShuffleTime
  call IncrementTimer
  
  ld hl, vTime
  call IncrementTimer
  
  ld a, [vTime+1]
  cp a, $01
  jp c, .doneTimer ; if the timer is less than $0100, skip to end
  
  ;otherwise reset the timer
  ld a, 0 
  ld [vTime], a 
  ld [vTime+1], a 
  
  ld hl, SquaresTiles
  ld a, [vFrameCountSquares]
  inc a
  call ArrayClampLooping
  ld [vFrameCountSquares], a 

.doneTimer

  ld a, [rMYBTNP]
  cp a, 0
  jr z, .doneWithButtons
  ld a, [rLFSR]
  ld [rLFSR+1], a ; lfsr = (lfsr << 8) + (vShuffleTime & $ff)
  ld a, [vShuffleTime]
  ld [rLFSR], a 
  
  ; check for B button press and change scene
  ld hl, rMYBTNP
  bit 4, [hl]
  jp z, .doneWithB
  ld hl, ScreenMainMenu
  call ChangeScene
  ret
.doneWithB
  call ShuffleButtonHandler
.doneWithButtons

  call ShufflePickAnimation
  
  ld a, [vAnimationFrame]
  inc a 
  ld [vAnimationFrame], a
  cp a, [hl]
  call z, ShuffleAdvanceState
  
  call ShufflePickAnimation
  ld a, [vAnimationFrame]
  call ArrayClamp
  ld [vAnimationFrame], a 
  
  call ShufflePickAnimation
  
  call ShuffleAnimate
  
  ret
  
ShuffleButtonHandler:
  ld a, [vState]
  cp a, S_Center
  jp z, CenterButtonHandler

  ld a, [vState]
  cp a, S_Right
  jp z, RightButtonHandler
  ld a, [vState]
  cp a, S_RightOut
  jp z, RightButtonHandler
  ld a, [vState]
  cp a, S_RightIn
  jp z, CenterButtonHandler

  ld a, [vState]
  cp a, S_Left
  jp z, LeftButtonHandler
  ld a, [vState]
  cp a, S_LeftOut
  jp z, LeftButtonHandler
  ld a, [vState]
  cp a, S_LeftIn
  jp z, CenterButtonHandler
  
  ld a, [vState]
  cp a, S_Up
  jp z, UpButtonHandler
  ld a, [vState]
  cp a, S_UpOut
  jp z, UpButtonHandler
  ld a, [vState]
  cp a, S_UpIn
  jp z, CenterButtonHandler
  
  ld a, [vState]
  cp a, S_Down
  jp z, DownButtonHandler
  ld a, [vState]
  cp a, S_DownOut
  jp z, DownButtonHandler
  ld a, [vState]
  cp a, S_DownIn
  jp z, CenterButtonHandler
  
  ret

CenterButtonHandler:
  call DoSomeShuffling
  
  ld hl, rMYBTNP
: bit 0, [hl]
  jp z, :+
  
  ld a, S_RightOut
  ld [vState], a
: bit 1, [hl]
  jp z, :+
  
  ld a, S_LeftOut
  ld [vState], a 
: bit 2, [hl]
  jp z, :+
  
  ld a, S_UpOut
  ld [vState], a 
: bit 3, [hl]
  jp z, :+
  
  ld a, S_DownOut
  ld [vState], a 
: ret

RightButtonHandler:
  ld hl, rMYBTNP
: bit 1, [hl]
  jp z, :+
  
  ld a, S_RightIn
  ld [vState], a 
: ret

LeftButtonHandler:
  ld hl, rMYBTNP
: bit 0, [hl]
  jp z, :+
  
  ld a, S_LeftIn
  ld [vState], a 
: ret

UpButtonHandler:
  ld hl, rMYBTNP
: bit 3, [hl]
  jp z, :+
  
  ld a, S_UpIn
  ld [vState], a 
: ret

DownButtonHandler:
  ld hl, rMYBTNP
: bit 2, [hl]
  jp z, :+
  
  ld a, S_DownIn
  ld [vState], a 
: ret



ShuffleAdvanceState:
  ld a, [vState]
  ld hl, ShuffleNextStates + 1
  ld b, 0
  ld c, a 
  add hl, bc
  ld a, [hl]
  ld [vState], a 
  ld a, 0
  ld [vAnimationFrame], a 
  ret
ShufflePickAnimation:
  ld a, [vState]
  ld b, 0
  ld c, a 
  ld hl, ShuffleAnimations + 1
  add hl, bc
  add hl, bc 
  ld c, [hl]
  inc hl
  ld b, [hl]
  ld h, b
  ld l, c 
  ret

ShuffleAnimate:
  ; hl has to hold the address of the animation
  
  inc hl
  ld b, 0 
  ld a, [vAnimationFrame]
  ld c, a 
  add hl, bc
  add hl, bc ; two bytes per entry
  
  ; hl points to xy offsets
  ld b, [hl]
  inc hl 
  ld c, [hl]
  ld a, 32
  ld e, a 
  ld hl, MY_OAM
  call DrawWholeCard ; hl memory location, b y, c x, e width, d wiggle
  
  ld a, [vState]
  cp a, S_RightIn
  jp z, HideSprites
  cp a, S_LeftIn
  jp z, HideSprites
  cp a, S_UpIn
  jp z, HideSprites
  cp a, S_DownIn
  jp z, HideSprites
  
  call ShowSprites
  ret

HideSprites:
  ld hl, MY_OAM
.testTile
  ld a, [hl]
  cp a, (2+4)*8 ; y < 5*8 => skip
  jp c, .goToNextTile
  cp a, (2+5+8)*8 ; y > (5+8)*8 => skip
  jp nc, .goToNextTile
  
  inc hl 
  ld a, [hl] ; x value
  dec hl 
  cp a, (1+7)*8 ; x < 7*8 => skip
  jp c, .goToNextTile
  cp a, (1+12)*8 ; x > 12*8 => skip
  jp nc, .goToNextTile
  
  inc hl 
  inc hl 
  inc hl 
  set OAMB_PRI, [hl]
  dec hl
  dec hl 
  dec hl 
  
.goToNextTile
  inc hl 
  inc hl 
  inc hl 
  inc hl 
  ld a, $A0
  cp a, l 
  jp nz, .testTile
  
  ret

ShowSprites:
  ld hl, MY_OAM
.loop
  inc hl
  inc hl 
  inc hl 
  res OAMB_PRI, [hl]
  inc hl
  ld a, $A0
  cp a, l 
  jp nz, .loop

  ret
  
ShuffleDraw:
  ld de, SAFE_DMA_LOCATION 
  ld a, HIGH(MY_OAM)
  call RunDMA
  
  ld hl, SquaresTiles
  inc hl 
  ld b, 0
  ld a, [vFrameCountSquares]
  ld c, a 
  add hl, bc 
  add hl, bc
  ld c, [hl]
  inc hl
  ld b, [hl]
  ld h, b
  ld l, c
  ld de, _VRAM+$100*16 + 1*16 ; tile number $101 is the sliding background
  ld bc, (SquaresTileset8 - SquaresTileset7) / 8
  call CopyRangeUnsafeBy8s
  
  ret

ShuffleTeardown:
  ret

DoSomeShuffling:
  call OneSwap
  call OneSwap
  call OneSwap
  call OneSwap
  call OneSwap
  call OneSwap
  ret

OneSwap: ; shuffles once and decrements vshuffleindex
  ; vShuffleIndex holds the index of the next card to swap with something
  ld a, [vShuffleIndex]
  cp a, 1
  jp z, .zeroIndex ; if we're swapping index 1 with index 0 skip it
  
  ld d, a 
  dec d ; this holds the highest index we could want to swap with

  call RandomUnderD ; takes d as limit (inclusive)
  ld e, a ; shuffle 2 is randint(vshuffleindex-1)
  ld c, d ; shuffle 1 is vshuffleindex
  ld hl, SHUFFLED_DECK
  call SwapCards ; arguments c and e as indices to swap, hl as array in memory
  
  ld a, [vShuffleIndex]
  dec a
  ld [vShuffleIndex], a ; decrement vshuffleindex so the next time around
  ; we do the next step of the shuffle
  ret
.zeroIndex
  ld a, [SHUFFLED_DECK]
  dec a 
  ld [vShuffleIndex], a 
  ret


ShuffleNextStates:
  db 13,
  db S_Center
  db S_Right ;def S_RightOut = 1
  db S_Right ; def S_Right = 2
  db S_Center ;def S_RightIn = 3
  db S_Left ;def S_LeftOut = 4
  db S_Left ;def S_Left = 5
  db S_Center ;def S_LeftIn = 6
  db S_Up ;def S_UpOut = 7
  db S_Up ;def S_Up = 8
  db S_Center ;def S_UpIn = 9
  db S_Down ;def S_DownOut = 10
  db S_Down ;def S_Down = 11
  db S_Center ;def S_DownIn = 12
ShuffleAnimations:
  db 13,
  dw ShuffleAnimationNone ; def S_Center = 0
  dw ShuffleAnimationRightOut ;def S_RightOut = 1
  dw ShuffleAnimationRight ; def S_Right = 2
  dw ShuffleAnimationRightIn ;def S_RightIn = 3
  dw ShuffleAnimationLeftOut ;def S_LeftOut = 4
  dw ShuffleAnimationLeft ;def S_Left = 5
  dw ShuffleAnimationLeftIn ;def S_LeftIn = 6
  dw ShuffleAnimationUpOut ;def S_UpOut = 7
  dw ShuffleAnimationUp ;def S_Up = 8
  dw ShuffleAnimationUpIn ;def S_UpIn = 9
  dw ShuffleAnimationDownOut ;def S_DownOut = 10
  dw ShuffleAnimationDown ;def S_Down = 11
  dw ShuffleAnimationDownIn ;def S_DownIn = 12

ShuffleAnimationNone:
  db 1, 56, 72
ShuffleAnimationRight: 
  db 1, 56, 115
ShuffleAnimationRightOut:
  db 9, 56, 72, 56, 80, 56, 88, 56, 96, 56, 103, 56, 108, 56, 112, 56, 114, 56, 115, 
ShuffleAnimationRightIn:
  db 8, 56, 115, 56, 104, 56, 96, 56, 88, 56, 80, 56, 76, 56, 73, 56, 72, 
ShuffleAnimationLeft:
  db 1, 56, 32
ShuffleAnimationLeftOut:
  db 9, 56, 72, 56, 64, 56, 56, 56, 49, 56, 42, 56, 36, 56, 35, 56, 33, 56, 32, 
ShuffleAnimationLeftIn:
  db 8, 56, 32, 56, 40, 56, 49, 56, 57, 56, 62, 56, 67, 56, 71, 56, 72, 
ShuffleAnimationUp:
db 1, -24, 72
ShuffleAnimationUpOut:
db 13, 56, 72, 48, 72, 40, 72, 32, 72, 24, 72, 16, 72, 8, 72, 0, 72, -7, 72, -14, 72, -18, 72, -23, 72, -24, 72
ShuffleAnimationUpIn:
db 10, 1, 72, 8, 72, 16, 72, 24, 72, 32, 72, 40, 72, 46, 72, 52, 72, 55, 72, 56, 72, 
ShuffleAnimationDown:
db 1, 136, 72
ShuffleAnimationDownOut:
db 13, 56, 72, 64, 72, 72, 72, 80, 72, 88, 72, 96, 72, 105, 72, 112, 72, 119, 72, 125, 72, 129, 72, 134, 72, 136, 72, 
ShuffleAnimationDownIn:
db 12, 136, 72, 128, 72, 120, 72, 112, 72, 104, 72, 96, 72, 88, 72, 80, 72, 68, 72, 61, 72, 58, 72, 56, 72, 
Shuffle.UITileData:
	db $00,$ff,$7f,$ff,$7f,$ff,$60,$ff,$6f,$ff,$6d,$fa,$6a,$fd,$6d,$fa ; top-left
	db $00,$ff,$ff,$ff,$ff,$ff,$00,$ff,$ff,$ff,$55,$aa,$aa,$55,$55,$aa ; top-middle
	db $00,$ff,$fe,$ff,$fe,$ff,$06,$ff,$f6,$ff,$56,$bf,$b6,$5f,$56,$bf ; top-right
	db $6a,$fd,$6d,$fa,$6a,$fd,$6d,$fa,$6a,$fd,$6d,$fa,$6a,$fd,$6d,$fa ; middle-left
	db $aa,$55,$55,$aa,$aa,$55,$55,$aa,$aa,$55,$55,$aa,$aa,$55,$55,$aa ; middle-middle
	db $b6,$5f,$56,$bf,$b6,$5f,$56,$bf,$b6,$5f,$56,$bf,$b6,$5f,$56,$bf ; middle-right
	db $6a,$fd,$6d,$fa,$6a,$fd,$6f,$ff,$60,$ff,$7f,$ff,$7f,$ff,$00,$ff ; bottom-left
	db $aa,$55,$55,$aa,$aa,$55,$ff,$ff,$00,$ff,$ff,$ff,$ff,$ff,$00,$ff ; bottom-middle
	db $b6,$5f,$56,$bf,$b6,$5f,$f6,$ff,$06,$ff,$fe,$ff,$fe,$ff,$00,$ff ; bottom-right
Shuffle.UITileDataEnd:

Shuffle.BigCard:
def VTS = VARIABLE_TILES_START
  db VTS,   VTS+1, VTS+1, VTS+2
  db VTS+3, VTS+4, VTS+4, VTS+5
  db VTS+3, VTS+4, VTS+4, VTS+5
  db VTS+3, VTS+4, VTS+4, VTS+5
  db VTS+3, VTS+4, VTS+4, VTS+5
  db VTS+3, VTS+4, VTS+4, VTS+5
  db VTS+3, VTS+4, VTS+4, VTS+5
  db VTS+6, VTS+7, VTS+7, VTS+8