;; This file is part of Moonsters
;;  Copyright (C) 2021 Dam Studios
;;
;;     Moonsters is free software: you can redistribute it and/or modify
;;     it under the terms of the GNU General Public License as published by
;;     the Free Software Foundation, either version 3 of the License, or
;;     (at your option) any later version.
;; 
;;     SHOOT TO MOVE 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 General Public License for more details.
;; 
;;     You should have received a copy of the GNU General Public License
;;     along with Moonsters  If not, see <https://www.gnu.org/licenses/>.

.include "man/entity_manager.h.s"
.include "cpctelera.h.s"


_num_entities:: .db 0
_first_free_entity:: .dw _entity_array
_entity_array::
	;;.ds max_entities * entity_size
	DefineEntityArray max_entities


man_entity_init::

	ld a, #00
	ld (_num_entities), a
	ld hl, #_entity_array
	ld (_first_free_entity), hl


	ret


;;INPUT
;;HL -> Puntero a la entidad a inicializar
;;Destroys: af, bc, de, hl
man_entity_create::

	;;Copiamos la entidad
	ld de, (_first_free_entity)
	ld bc, #entity_size
	ldir

	;;Aumentamos numero de entidades
	ld a, (_num_entities)
	inc a
	ld (_num_entities), a

	;;Movemos el puntero a primera zona libre
	ld hl, (_first_free_entity)
	ld bc, #entity_size
	add hl, bc
	ld (_first_free_entity), hl

	ret

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;,
;; ENTITY FORALL
;; Ejecuta una funcion para cada entidad
;; Pasa el puntero a la entidad por ix
;; INPUT:
;; 	HL: puntero a la funcion
;; Registros destruidos:
;; HL, IX, BC, AF
;; OJO: la funcion que se le pasa puede destruir mas registros
;; NO DEBE DESTRUIR IX NUNCA
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
man_entity_forall::

	;;Cambiamos el call
	ld (funcionForAll+1), hl
	ld a, (_num_entities) ;;cargamos contador de entidades
	ld ix, #_entity_array ;;cargamos en ix el array de entidades

loopForAll:
	;; a es el contador de entidades
	cp #0 ;;Si el contador es 0 paramos
	jr z, finalForAll
	push af

funcionForAll:
	call #0000

	ld bc, #entity_size
	add ix, bc

	pop af
	dec a
	jr loopForAll

finalForAll:

	ret


;;
;;GET ENTITY VECTOR
;; Devuelve el vector de entidades 
;; Return:
;; 	IX-> puntero al vector de entidades
;; 	A -> Numero de entidades
;; OJO UTILIZAR SOLO CUANDO SEA NECESARIO
;; SI SE VA A HACER UN BUCLE NORMAL POR TODAS LAS ENTIDADES MEJOR USAR FORALL
man_entity_getArray::
	ld ix, #_entity_array
	ld a, (_num_entities)	

	ret


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;,
;; ENTITY UPDATE
;; Destruye aquellas entidades marcadas para destruir
;; Registros destruidos:
;; HL, IX, BC, AF
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
man_entity_update::


	ld a, (_num_entities) ;;cargamos contador de entidades
	ld ix, #_entity_array ;;cargamos en ix el array de entidades
	;; a es el contador de entidades
	cp #0 ;;Si el contador es 0 paramos
	jr z, finalBucle

loopUpdate:

	push af ;;evitamos perder el contador de entidades

	ld a, e_type(ix)
	cp #e_type_destroy
	jr nz, continuarBucle;;Si no esta marcada para destruir

	ld d, e_oldVideo_l(ix)
    	ld e, e_oldVideo_h(ix) ;;cargamos la posicion antigua
    	ld a, #0x00
    	ld b, e_h(ix)
    	ld c, e_w(ix)
    	call cpct_drawSolidBox_asm ;;Borramos lo antiguo
   	.globl cpct_drawSolidBox_asm


	;;si esta marcada para destruir
	ld bc, #entity_size
	;;cambiamos la ix actual a de
	ld__de_ix ;;opCode no documentado cpctelera
	ld hl, (_first_free_entity)
	sbc hl, bc ;;ponemos hl apuntando a la ultima entidad

	ld (_first_free_entity), hl ;;modificamos first free entity

	ldir

	;;reducimos el numero de entidades
	ld a, (_num_entities)
	dec a
	ld (_num_entities), a


	;;comprobamos que el contador no esta ya en cero
;;bajamos uno mas el contador
	pop af
	;;comprobamos que el contador no esta ya en el ultimo
	cp #01
	jr z, continuarBuclePush

	dec a
	push af


continuarBucle:
	
	ld de, #entity_size
	add ix, de

	pop af
	;;comprobamos si es el final
	dec a
	cp #0
	jr nz, loopUpdate ;;si no es cero seguimos
finalBucle:

	ret

continuarBuclePush:

	push af
	jr  continuarBucle