/*
 * File: z_en_dy_extra.c
 * Overlay: ovl_En_Dy_Extra
 * Description: Spiral Beams (Great Fairy Fountains)
 */

#include "z_en_dy_extra.h"

#include "gfx.h"
#include "gfx_setupdl.h"
#include "printf.h"
#include "segmented_address.h"
#include "sfx.h"
#include "sys_matrix.h"
#include "terminal.h"
#include "translation.h"
#include "z_lib.h"
#include "play_state.h"

#include "assets/objects/object_dy_obj/object_dy_obj.h"

#define FLAGS (ACTOR_FLAG_UPDATE_CULLING_DISABLED | ACTOR_FLAG_DRAW_CULLING_DISABLED)

void EnDyExtra_Init(Actor* thisx, PlayState* play);
void EnDyExtra_Destroy(Actor* thisx, PlayState* play);
void EnDyExtra_Update(Actor* thisx, PlayState* play);
void EnDyExtra_Draw(Actor* thisx, PlayState* play);

void EnDyExtra_Wait(EnDyExtra* this, PlayState* play);
void EnDyExtra_Disappear(EnDyExtra* this, PlayState* play);

ActorProfile En_Dy_Extra_Profile = {
    /**/ ACTOR_EN_DY_EXTRA,
    /**/ ACTORCAT_PROP,
    /**/ FLAGS,
    /**/ OBJECT_DY_OBJ,
    /**/ sizeof(EnDyExtra),
    /**/ EnDyExtra_Init,
    /**/ EnDyExtra_Destroy,
    /**/ EnDyExtra_Update,
    /**/ EnDyExtra_Draw,
};

void EnDyExtra_Destroy(Actor* thisx, PlayState* play) {
}

void EnDyExtra_Init(Actor* thisx, PlayState* play) {
    EnDyExtra* this = (EnDyExtra*)thisx;

    PRINTF("\n\n");
    PRINTF(VT_FGCOL(YELLOW) T("☆☆☆☆☆ 大妖精効果 ☆☆☆☆☆ %d\n", "☆☆☆☆☆ Big fairy effect ☆☆☆☆☆ %d\n") VT_RST,
           this->actor.params);
    this->type = this->actor.params;
    this->scale.x = 0.025f;
    this->scale.y = 0.039f;
    this->scale.z = 0.025f;
    this->homePos = this->actor.world.pos;
    this->actor.gravity = -0.2f;
    this->alphaFac = 1.0f;
    this->timer = 60;
    this->actionFunc = EnDyExtra_Wait;
}

void EnDyExtra_Wait(EnDyExtra* this, PlayState* play) {
    Math_ApproachF(&this->actor.gravity, 0.0f, 0.1f, 0.005f);
    if (this->actor.world.pos.y < -55.0f) {
        this->actor.velocity.y = 0.0f;
    }
    if ((this->timer == 0) && this->startDisappearing) {
        this->timer = 200;
        this->actionFunc = EnDyExtra_Disappear;
    }
}

void EnDyExtra_Disappear(EnDyExtra* this, PlayState* play) {
    Math_ApproachF(&this->actor.gravity, 0.0f, 0.1f, 0.005f);
    if ((this->timer == 0) || (this->alphaFac < 0.02f)) {
        Actor_Kill(&this->actor);
        return;
    }
    Math_ApproachZeroF(&this->alphaFac, 0.03f, 0.05f);
    if (this->actor.world.pos.y < -55.0f) {
        this->actor.velocity.y = 0.0f;
    }
}

void EnDyExtra_Update(Actor* thisx, PlayState* play) {
    EnDyExtra* this = (EnDyExtra*)thisx;

    DECR(this->timer);
    this->actor.scale.x = this->scale.x;
    this->actor.scale.y = this->scale.y;
    this->actor.scale.z = this->scale.z;
    Actor_PlaySfx(&this->actor, NA_SE_PL_SPIRAL_HEAL_BEAM - SFX_FLAG);
    this->actionFunc(this, play);
    Actor_MoveXZGravity(&this->actor);
}

void EnDyExtra_Draw(Actor* thisx, PlayState* play) {
    static Color_RGBA8 sPrimColors[] = { { 255, 255, 170, 255 }, { 255, 255, 170, 255 } };
    static Color_RGBA8 sEnvColors[] = { { 255, 100, 255, 255 }, { 100, 255, 255, 255 } };
    static u8 sVerticesAlphaType[] = {
        2, 1, 1, 2, 0, 0, 2, 1, 0, 2, 1, 0, 2, 1, 0, 2, 1, 0, 2, 1, 0, 2, 1, 0, 1, 2, 0
    };
    EnDyExtra* this = (EnDyExtra*)thisx;
    GraphicsContext* gfxCtx = play->state.gfxCtx;
    s32 pad;
    Vtx* vertices = SEGMENTED_TO_VIRTUAL(gGreatFairySpiralBeamVtx);
    s32 i;
    u8 alphaVals[3];

    alphaVals[0] = 0.0f;
#ifndef AVOID_UB
    alphaVals[1] = (s8)(this->alphaFac * 240.0f);
    alphaVals[2] = (s8)(this->alphaFac * 255.0f);
#else
    alphaVals[1] = (u8)(this->alphaFac * 240.0f);
    alphaVals[2] = (u8)(this->alphaFac * 255.0f);
#endif

    for (i = 0; i < 27; i++) {
        if (sVerticesAlphaType[i] != 0) {
            vertices[i].n.a = alphaVals[sVerticesAlphaType[i]];
        }
    }

    OPEN_DISPS(gfxCtx, "../z_en_dy_extra.c", 294);

    Gfx_SetupDL_25Xlu(play->state.gfxCtx);
    gSPSegment(POLY_XLU_DISP++, 0x08,
               Gfx_TwoTexScroll(play->state.gfxCtx, G_TX_RENDERTILE, play->state.frames * 2, 0, 0x20, 0x40, 1,
                                play->state.frames, play->state.frames * -8, 0x10, 0x10));
    gDPPipeSync(POLY_XLU_DISP++);
    MATRIX_FINALIZE_AND_LOAD(POLY_XLU_DISP++, play->state.gfxCtx, "../z_en_dy_extra.c", 307);
    gDPSetPrimColor(POLY_XLU_DISP++, 0, 0x80, sPrimColors[this->type].r, sPrimColors[this->type].g,
                    sPrimColors[this->type].b, 255);
    gDPSetEnvColor(POLY_XLU_DISP++, sEnvColors[this->type].r, sEnvColors[this->type].g, sEnvColors[this->type].b, 128);
    gSPDisplayList(POLY_XLU_DISP++, gGreatFairySpiralBeamDL);

    CLOSE_DISPS(gfxCtx, "../z_en_dy_extra.c", 325);
}
