#define NENT_DEPRECATED
#include "entity.h"
#include "room.h"
#include "asm.h"
#include "sound.h"
#include "player.h"
#include "functions.h"
#include "effects.h"

typedef struct {
    Entity base;
    u8 filler[0x4];
    u32 unk6c;
    u32 unk70;
    u16 tilePos;
    u16 unk76;
    u16 unk78;
    u16 unk7a;
} PlayerCloneEntity;

extern Entity* sub_08077CF8(u32 subtype, u32 form, u32 parameter, u32 unk);
extern const s16 gUnk_080B4468[];

void PlayerClone_Init(PlayerCloneEntity*);
void PlayerClone_Action1(PlayerCloneEntity*);
void PlayerClone_Action2(PlayerCloneEntity*);
void sub_08084B1C(PlayerCloneEntity*);
void sub_08084CAC(PlayerCloneEntity*);

void PlayerClone(Entity* this) {
    static void (*const actionFuncs[])(PlayerCloneEntity*) = {
        PlayerClone_Init,
        PlayerClone_Action1,
        PlayerClone_Action2,
    };

    actionFuncs[this->action]((PlayerCloneEntity*)this);
}

void PlayerClone_Init(PlayerCloneEntity* this) {
    super->action = 1;
    super->spriteRendering.b3 = 2;
    super->spritePriority.b0 = 4;
    super->x.HALF.HI = (super->x.HALF.HI & 0xfff0) | 8;
    super->y.HALF.HI = (super->y.HALF.HI & 0xfff0) | 8;
    this->tilePos = COORD_TO_TILE(super);
    InitializeAnimation(super, 8);
    SetTile(0x4016, this->tilePos, super->collisionLayer);
    SoundReq(SFX_112);
}

const u16 PlayerCloneCollisions[] = { 0x2206, 0x6044, 0x4460, 0x622 };

void PlayerClone_Action1(PlayerCloneEntity* this) {
    static const Hitbox PlayerCloneHitbox = { 0, -3, { 5, 3, 3, 5 }, 6, 6 };

    if (gPlayerState.chargeState.action == 5) {
        super->spriteSettings.draw = 1;
        super->health = 1;
        super->action = 2;
        super->updatePriority = 6;
        super->hitbox = (Hitbox*)&PlayerCloneHitbox;
        super->field_0xf = (super->type + 1) * 15;
        this->unk78 = super->x.HALF.HI - gPlayerEntity.x.HALF.HI;
        this->unk7a = super->y.HALF.HI - gPlayerEntity.y.HALF.HI;
        if ((this->unk78 != 0) && (this->unk7a != 0)) {
            ((PlayerCloneEntity*)gPlayerClones[super->type])->unk70 = 1;
        }
        sub_08000152(0x315, this->tilePos, super->collisionLayer);
        super->child = sub_08077CF8(1, super->type + 1, 0, ((GenericEntity*)gPlayerState.item)->field_0x68.HALF.LO);
        if (super->child != NULL) {
            super->child->parent = super;
        }
        sub_0801766C(super);
        sub_0806FDA0(super);
        PlayerClone_Action2(this);
    } else if (gPlayerState.chargeState.action != 4) {
        sub_08000152(0x315, this->tilePos, super->collisionLayer);
        gPlayerClones[super->type] = NULL;
        DeleteThisEntity();
    } else {
        super->spriteSettings.draw ^= 1;
    }
}

void PlayerClone_Action2(PlayerCloneEntity* this) {
    u32 index;

    if (super->field_0xf == 1) {
        SoundReq(SFX_PLY_VO2);
        super->field_0xf--;
    } else if (super->field_0xf != 0) {
        super->field_0xf--;
    }

    if (gPlayerState.chargeState.action == 5 && gPlayerClones[super->type] != NULL && gPlayerState.framestate != 19 &&
        super->health != 0) {
        if (gPlayerEntity.iframes >= 1) {
            gPlayerState.chargeState.action = 1;
        } else {
            sub_080B1AA8(super);
            sub_08084B1C(this);
            super->x.HALF.HI = gPlayerEntity.x.HALF.HI + this->unk78;
            super->y.HALF.HI = gPlayerEntity.y.HALF.HI + this->unk7a;
            sub_08084CAC(this);
            sub_080085B0(super);
            if ((super->collisions & 0x6666) != 0x6666) {
                for (index = 0; index <= 3; index++) {
                    if (PlayerCloneCollisions[index] == (PlayerCloneCollisions[index] & super->collisions)) {
                        break;
                    }
                }

                if (index == 4) {
                    super->actionDelay = 0;
                    super->spriteSettings.draw = 1;
                    return;
                } else {
                    if (super->actionDelay != 0) {
                        if (--super->actionDelay != 0) {
                            super->spriteSettings.draw ^= 1;
                            return;
                        }
                    } else {
                        super->actionDelay = 30;
                        return;
                    }
                }
            }
            gPlayerState.chargeState.action = 1;
            return;
        }
    }
    DeleteClones();
    CreateFx(super, FX_SPARKLE_SECRET, 0);
    DeleteEntity(super->child);
    SoundReq(SFX_18F);
    DeleteThisEntity();
}

void sub_08084B1C(PlayerCloneEntity* this) {
    super->flags = gPlayerEntity.flags;
    super->spriteVramOffset = gPlayerEntity.spriteVramOffset;
    super->frameIndex = gPlayerEntity.frameIndex;
    super->frameSpriteSettings = gPlayerEntity.frameSpriteSettings;
    super->spriteIndex = gPlayerEntity.spriteIndex;
    super->direction = gPlayerEntity.direction;
    super->animationState = gPlayerEntity.animationState;
    super->spriteSettings.flipX = gPlayerEntity.spriteSettings.flipX;
    super->spriteRendering.b3 = gPlayerEntity.spriteRendering.b3;
    super->spritePriority.b0 = gPlayerEntity.spritePriority.b0;
    super->spriteOrientation.flipY = gPlayerEntity.spriteOrientation.flipY;
    super->collisionLayer = gPlayerEntity.collisionLayer;
    super->flags2 = gPlayerEntity.flags2;
    super->hitType = gPlayerEntity.hitType;
    super->field_0x3c = gPlayerEntity.field_0x3c;
    super->hurtType = gPlayerEntity.hurtType;
    CopyPosition(super, super->child);
    if (gPlayerState.field_0x3[1] != 0) {
        super->child->damage = gPlayerState.item->damage;
        super->child->frameIndex = gPlayerState.item->frameIndex;
        super->child->spriteSettings.flipX = gPlayerState.item->spriteSettings.flipX;
        super->child->spriteRendering.b3 = gPlayerState.item->spriteRendering.b3;
        super->child->spritePriority.b0 = gPlayerState.item->spritePriority.b0;
        if (super->child->spriteSettings.flipX) {
            super->child->hitbox->offset_x = -super->child->hitbox->offset_x;
        }
    }
    sub_0806FEBC(super, 0, 0);
    sub_0806FEBC(super, 1, 0);
    sub_0806FEBC(super, 2, super);
    sub_0806FEBC(super, 3, 0);
    sub_08078E84(super->child, super);
}

void sub_08084CAC(PlayerCloneEntity* this) {
    const s16* ptr;

    if (((PlayerCloneEntity*)gPlayerClones[super->type])->unk70 == 0) {
        ptr = &gUnk_080B4468[super->animationState & 6];
        if (sub_080B1B54(GetTileType(COORD_TO_TILE_OFFSET(super, -ptr[0], -ptr[1]), super->collisionLayer)) == 0x72) {
            ((PlayerCloneEntity*)gPlayerClones[0])->unk6c |= (1 << super->type);
        } else {
            ((PlayerCloneEntity*)gPlayerClones[0])->unk6c &= ~(1 << super->type);
        }
    }
}
