;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;; GAME MANAGER ;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;--------- INCLUDES ---------
.include "cpctelera.h.s"
.include "../cpct_globals.h.s"
.include "man_entity.h.s"
.include "man_animation.h.s"
.include "../sys/render.h.s"
.include "../sys/input.h.s"
.include "../sys/physics.h.s"
.include "../sys/collision.h.s"
;----------------------------

_endgame_flag::                          .db 0x00
_player_puntuation::                     .dw 0x00
_player_puntuation_render::              .asciz "0000"
_default_player_puntuation_render::      .asciz "0000"

_level_render::                          .asciz "01-09"
_actual_lvl::                            .db 0x01
max_levels =  10

_flag_game_restart:: .db 0x00

;;----------------------------------------------------------
;;      INICIO DEL MOTOR DEL JUEGO Y TODAS SUS FUNCIONES 
;;----------------------------------------------------------

man_game_run::

    ;call cpct_disableFirmware_asm   ;; SE DESACTIVA EL FIRMWARE

   reset_to_title_screen:

        ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
        ;;  Se inicia la pantalla de titulo  ;;;
        ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;      
        call man_game_title  
                

        ;; RESETEO DE PUNTUACION CUANDO EL JUEGO SE REINICIA
        call man_game_reset_values

   reset_to_ingame:
        ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
        ;;;  Se inicia la pantalla de juego  ;;;
        ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
                call man_game_ingame

        ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
        ;;; Update del juego, actualiza todo ;;;
        ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
      
                call man_game_update

        ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
        ;;; Pantalla de finalizado el juego ;;;;
        ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
                call man_game_endgame
                call input_detectAnyKey         ;;llamada para detect key

      ;; COMPROBACION DE QUE EL JUEGO DEBE O REINICIARSE O PASAR DE NIVEL

      call man_game_getRestartStatus
      ld c, #0

      cp c

      jr z, reset_to_title_screen

   jr reset_to_ingame

ret

;;---------------------------
;;      GAME TITLE SCREEN 
;;---------------------------
man_game_title:

    call render_title               ;;renderiza la pantalla de titulo
    call input_detectAnyKey

ret

;;---------------------------
;;      INGAME SCREEN 
;;---------------------------
man_game_ingame::

    ld hl, #_flag_game_restart
    inc (hl)

    call man_game_desactivateEndFlag

    call render_game                ;;  Se renderiza el Juego
    call man_entity_init            ;;  Inicializador del Juego
   

    call man_entity_create_all      ;; Crea todas las Entidades
ret

;;---------------------------
;;      ENDGAME SCREEN 
;;---------------------------

man_game_endgame::

    ;; COMPROBACION DEL ESTADO DEL PLAYER
    call man_entity_getPlayerDeadFlag

    ld c, #0x00

    cp c
    
    ;; ==================================

    jr z, endgame_exit


    ;; CUANDO EL PLAYER HA MUERTO HACE ESTO

      endgame_deadPlayer:

        ;; RESETEO DE PUNTUACION
            call man_game_resetPuntuation
        ;; ========================

        ;; SE ELIMINAN LAS ENTIDADES
            call man_entity_reset
        ;; =========================

        ;; RENDERIZA LA PANTALLA DE MUERTE DEL PLAYER
            call render_deadPlayer
        ;; =======================================
ret

    ;; CUANDO EL PLAYER SALE DEL NIVEL HACE ESTO
    endgame_exit:

        ;; SE BORRAN TODAS LAS ENTIDADES
        call man_entity_reset
    
        ld a, (_actual_lvl)
        ld c, #max_levels

        cp c
        
        jr z, game_finished

        go_to_next_level:

            ;; SE RENDERIZA LA PANTALLA DE VICTORIA
            call render_endgame

            ret

        game_finished:
            

            xor a
            ld (_flag_game_restart), a

            ;; SE RENDERIZA LA PANTALLA DE JUEGO COMPLETADO
            call render_finished
        
        
ret

;;---------------------------
;;      INGAME UPDATE 
;;---------------------------
man_game_update::

    loop_update:

        ;cpctm_setBorder_asm HW_MAGENTA
        call collision_update   ;;  COLLISION UPDATE

        ;cpctm_setBorder_asm HW_RED
        call render_update

        ;cpctm_setBorder_asm HW_GREEN
        call input_update           ;; INPUT UPDATE

        ;cpctm_setBorder_asm HW_WHITE
        call physics_update         ;;  PHYSICS UPDATE

        call man_anim_update        ;;  ANIMATION UPDATE

        ;cpctm_setBorder_asm HW_BLUE
        call man_entity_update      ;;  ENTITY MANAGER UPDATE


        ;; ACTIVADO DE VSYNC PARA LOS ULTIMOS NIVELES (PARA MEJORAR EL RENDIMIENTO)

        ld a, (_actual_lvl)
        ld c, #6

        cp c
        call c, cpct_waitVSYNC_asm     ;;Wait VSYNC

        cpctm_setBorder_asm HW_ORANGE

    ld a, (_endgame_flag)
    ld c, #0x00

    cp c

    jr z, loop_update
ret

;;-----------------------------
;;      RESETEO DE VALORES
;;-----------------------------
man_game_reset_values::

    ;; RESETEO DEL NIVEL A CARGAR
    call man_game_resetActualLevel

    ;; RESETEO DE LA PUNTUACION
    call man_game_resetPuntuation

ret

;; ACTIVA EL FLAG DE FIN DE JUEGO
man_game_activateEndFlag::

    ld hl, #_endgame_flag
    inc (hl)
ret

;; DESACTIVA EL FLAG DE FIN DE JUEGO
man_game_desactivateEndFlag::

    ld hl, #_endgame_flag
    ld a, #0x00

    ld (hl), a
ret

;; [A] >> RESTART FLAG
man_game_getRestartStatus::

    ld a, (_flag_game_restart)
ret

;; [BC] << PUNTUACION A SUMAR
man_game_increasePuntuation::

    ld de, (_player_puntuation)         ;; DE COGE EL CONTENIDO PUNTUACION NUMERICA
    ld hl, #_player_puntuation          ;; HL APUNTA A LA PUNTUACION NUMÉRICA

    ld a, e                             ;; METEMOS EN A, EL VALOR DE E
    add c                               ;; SUMAMOS EL VALOR QUE HAY EN C

    daa                                 ;; ESTA INSTRUCCION SIRVE PARA CONVERTIR EL RESULTADO ANTERIOR EN DECIMAL
                                        ;; Y METE EL NUMERO DECIMAL EN A

    ;; ALMACENAMOS EL NUEVO VALOR EN MEMORIA
    ld (hl), a
    inc hl

    ld e, a                    ;; METEMOS EN E EL NUEVO VALOR CREANDO ANTERIORMENTE 
    ld a, d                    ;; METEMOS EN A EL VALOR QUE TIENE D (POR SI BC ES MAS GRANDE QUE UN BYTE)
    
        adc b                      ;; SUMAMOS LO QUE HAY EN B Y LE AÑADIMOS EL CARRY FLAG
    
        daa                        ;; CONVERTIMOS EL RESULTADO ANTERIOR EN DECIMAL
    
    ld d, a                    ;; METEMOS EN D EL NUEVO VALOR

    ;; ALMACENAMOS EL NUEVO VALOR EN MEMORIA
    ld (hl), a
    inc hl
    
    ld hl, #_player_puntuation_render

    ;; PARTE ALTA DE D

    ld a, d

    rra                        
    rra
    rra
    rra
    
    and #0x0F
    add #48

    ld (hl), a
    inc hl

    ;; PARTE BAJA DE D

    ld a, d
    
    and #0x0F
    add #48

    ld (hl), a
    inc hl

    ;; PARTE ALTA DE E

    ld a, e

    rra                        
    rra
    rra
    rra
    
    and #0x0F
    add #48

    ld (hl), a
    inc hl

    ;; PARTE BAJA DE E

    ld a, e
    
        and #0x0F
        add #48

    ld (hl), a

ret 

;; [HL] >> POINTER TO PUTUATION
man_game_getPlayerPuntuation_render::

    ld hl, #_player_puntuation_render

ret

man_game_resetPuntuation::

    ;; RESETEO DE PUNTUACION NUMERICA
        ld hl, #_player_puntuation
        ld bc, #0x000   
        ld (hl), b
        inc hl

        ld (hl), c
    ;; ==============================

    ;; RESETEO DE PUNTUACIÓN ASCII

        ld hl, #_player_puntuation_render
        
        ld a, #4

        reset_puntuation_loop:

            ld (hl), #'0'
            inc hl
            
            dec a

        jr nz, reset_puntuation_loop

    ;; ======================
ret

;; [A] >> NIVEL ACTUAL
man_game_getActualLevel::

    ld a, (_actual_lvl)
ret

;; [HL] >> STRING DEL NIVEL ACTUAL
man_game_getActualLevel_render::

    ld hl, #_level_render
ret

;; INCREMENTA EL NIVEL ACTUAL
man_game_incActualLevel::

    ;; AUMENTAMOS EL CONTADOR NUMERICO

    ld hl, #_actual_lvl
    inc (hl)

    ;; LO CONVERTIMOS A ASCII Y LO GUARDAMOS

    ld a, (_actual_lvl)

    and #0x0F
    add #48

    ld hl, #_level_render
    inc hl
    
    ld (hl), a

ret

;; RESETEA EL CONTADOR DE NIVELES
man_game_resetActualLevel::

    ;; RESETEO DE NIVEL NUMERICO
    ld a, #1
    ld (_actual_lvl), a


    ;; RESETEO DEL CONTADOR DE NIVELES DEL RENDER

    ld hl, #_level_render
    inc hl
    
    ld (hl), #'1'
ret