;;-----------------------------LICENSE NOTICE------------------------------------
;;  This file is part of The Last Fungus: An Amstrad CPC Game 
;;  Copyright (C) 2021 Miguel Perez Tarruella / Antonio Jose Fernandez Belliure / 
;;                     David Martinez Garcia / Ocacho Games (@OcachoGames)
;;
;;  This program is free software: you can redistribute it and/or modify
;;  it under the terms of the GNU Lesser General Public License as published by
;;  the Free Software Foundation, either version 3 of the License, or
;;  (at your option) any later version.
;;
;;  This program is distributed in the hope that it will be useful,
;;  but WITHOUT ANY WARRANTY; without even the implied warranty of
;;  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
;;  GNU Lesser General Public License for more details.
;;
;;  You should have received a copy of the GNU Lesser General Public License
;;  along with this program.  If not, see <http://www.gnu.org/licenses/>.
;;------------------------------------------------------------------------------

;;====================================================================
;; GLOBL INCLUDES
;;====================================================================

;;Managers
.include "man/entity.h.s"
.include "man/game.h.s"
.include "man/level_loader.h.s"

;;Resources
.include "resources/players_animations.h.s"
.include "resources/enemies_animations.h.s"

;;Macros
.include "macros/math.h.s"

;;====================================================================
;; GRAVITY STATE MACHINE MACROS
;;====================================================================  

.macro SELECT_GRAVITY_PLAYER2_OR_ENEMY_ANIM_MACRO _state, _facing

    ld a, (#m_gamemode)
    IS_EQUALS 0
    jr z, singleplayer_'_state'_'_facing

    ;;Is multiplayer, so the anim should be the player 2
    ld hl, #player2_'_state'_'_facing
    jr update_gravity_'_state

    singleplayer_'_state'_'_facing:

    ld a, (#m_current_level)
    IS_EQUALS 1
    jr z, label_walker_easy_'_state'_'_facing

    ;;walker_difficult_'state:
    ld hl, #walker_difficult_'_state'_'_facing
    jr update_gravity_'_state

    label_walker_easy_'_state'_'_facing:

    ld hl, #walker_easy_'_state'_'_facing

    jr update_gravity_'_state

.endm 

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Parameters
;;  - _state: State we want to define (IDLE, RUN...)
;; Objetive: Define the state for gravitable entities
;; Modifies: A, HL
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
.macro DEFINE_GRAVITY_ANIM_STATE _state

player_gravity_'_state:

    ;;Check what player is
    IS_ENTITY_GIVEN_TYPE_IX e_type_player1
    jr nz, is_player_1_'_state

    ;;is_player_2/enemy_'_state

        ld a, e_facing_right(ix)
        IS_EQUALS 1
        jr z, facing_right_'_state'_p2_or_enemy_gravity

        ;;facing_left_'_state':
            SELECT_GRAVITY_PLAYER2_OR_ENEMY_ANIM_MACRO _state, left
    
        facing_right_'_state'_p2_or_enemy_gravity:
            SELECT_GRAVITY_PLAYER2_OR_ENEMY_ANIM_MACRO _state, right

    is_player_1_'_state:

        ld a, e_facing_right(ix)
        IS_EQUALS 1
        jr z, facing_right_'_state'_p1

        ;;facing_left_'_state':
            ld hl, #player1_'_state'_left
            jr update_gravity_'_state
        
        facing_right_'_state'_p1:
            ld hl, #player1_'_state'_right


    update_gravity_'_state:

    ld e_anim_b1(ix), l
    ld e_anim_b2(ix), h

    ld a, (hl)
    ld e_anim_counter(ix), a
ret

.endm

;;===================================================================
;; STATES
;;===================================================================

DEFINE_GRAVITY_ANIM_STATE idle
DEFINE_GRAVITY_ANIM_STATE run
DEFINE_GRAVITY_ANIM_STATE jump
DEFINE_GRAVITY_ANIM_STATE die
DEFINE_GRAVITY_ANIM_STATE shooting

;;====================================================================
;; FUNCTIONS
;;====================================================================

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Pre requirements
;;  - IX: should contain the memory direction for the player
;; Objetive: Updates the anim state machine for entities with gravity
;; Modifies: A, HL
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
man_gravity_state_machine_update::
    
    ;;Check if the entity is set to dying_animation
    IS_ENTITY_GIVEN_TYPE_IX e_type_dying_animation
    jr z, not_dying_animation_gravity

    ;;Check if die was the last state
    ld a, e_last_anim_state(ix)
    IS_EQUALS 3
    ret z
    ld e_last_anim_state(ix), #3

    call player_gravity_die
    ret

    not_dying_animation_gravity:

    ld l, e_bullet_ref_b1(ix)
    ld h, e_bullet_ref_b2(ix)

    ld a, (hl)      ;;Charging in A the type of the bullet
    IS_EQUALS 00
    jr z, not_shooting_animation_gravity

    ;;shooting_animation_gravity:
    ld a, e_last_anim_state(ix)
    IS_EQUALS 4
    ret z
    ld e_last_anim_state(ix), #4

    call player_gravity_shooting
    ret

    not_shooting_animation_gravity:

    ;;Check if player_gravity is grounded
    ld a, e_is_grounded(ix)
    IS_EQUALS 1
    jr nz, is_not_grounded

    ;;Check if player_gravity is moving
    ld a, e_vel_x(ix)
    IS_EQUALS 0
    jr nz, is_moving

;;is_not_moving:
    ;;Check if idle was the last state
    ld a, e_last_anim_state(ix)
    IS_EQUALS 0
    ret z
    ld e_last_anim_state(ix), #0

    call player_gravity_idle
    ret


is_moving:
    ;;Check if run was the last state
    ld a, e_last_anim_state(ix)
    IS_EQUALS 1
    jr nz, execute_anim_run

    ;;Same state == last_state. Check if different facing right
    ld a, e_last_facing_right(ix)
    ld b, e_facing_right(ix)
    IS_EQUALS_REGISTER b
    ret z

    execute_anim_run:
    ld e_last_anim_state(ix), #1
    ld a, e_facing_right(ix)
    ld e_last_facing_right(ix), a
    call player_gravity_run
    ret


is_not_grounded:
    ;;Check if jump was the last state
    ld a, e_last_anim_state(ix)
    IS_EQUALS 2
    jr nz, execute_anim_jump
    
    ;;Same state == last_state. Check if different facing right
    ld a, e_last_facing_right(ix)
    ld b, e_facing_right(ix)
    IS_EQUALS_REGISTER b
    ret z

    execute_anim_jump:
    ld e_last_anim_state(ix), #2
    ld a, e_facing_right(ix)
    ld e_last_facing_right(ix), a
    call player_gravity_jump
    
ret