// BanjoDecomp: CC/ma/clanker.c
#include <ultra64.h>
#include "core1/core1.h"
#include "functions.h"
#include "variables.h"

#include "core2/modelRender.h"

extern BKCollisionTriangle *func_8028EF48(void);
extern void func_8030E9FC(enum sfx_e uid, f32 arg1, f32 arg2, u32 arg3, f32 arg4[3], f32 arg5, f32 arg6);
extern void func_8030EA54(enum sfx_e uid, f32 arg1, f32 arg2, u32 arg3, f32 arg4[3], f32 arg5, f32 arg6);
extern void func_8031CE28(s32, s32, f32);
void timed_exitStaticCamera(f32);
extern void func_80340200(Struct83s *, f32[3], f32[3], f32, f32[3], s16[3], BKVertexList *, f32[3]);
extern int func_80340020(Struct83s *, f32[3], f32[3], f32, f32[3], BKVertexList *, f32[3], f32[3]);

extern void boneTransformList_getBoneScale(BoneTransformList *, s32, f32[3]);
extern void boneTransformList_setBoneScale(BoneTransformList *, s32, f32[3]);
extern void func_8033A9A8(BoneTransformList *, s32, f32[3]);
extern void modelRender_setAppendageVisibility(s32, s32);
extern void modelRender_setBoneTransformList(BoneTransformList *);
extern void func_8028FAB0(f32[3]);
extern void baModel_802921D4(f32[3]);

/* .data */
f32 maClankerJiggyPosition[3] = {5700.0f, 4300.0f, 0.0f};
f32 D_80389C0C[3] = {0.0f,  27.0f, 0.0f};
f32 D_80389C18[3] = {0.0f, -27.0f, 0.0f};
f32 maClankerRaisedSoundPosition[3] = {4000.0f, 3500.0f, 0.0f};

/* .bss */
struct {
    SkeletalAnimation *skeletonAnim;
    u8 sfxsourceIdx;
    //u8 pad5[0x3];
    f32 unk8; // screw timer?
    f32 meetDialogPosition[3];
    Struct83s *unk18;
    BKCollisionList *collisionList;
    u8 triggerMeetDialog;
    u8 currentState;
    //u8 pad22[0x2];
    BKModelBin * model;
    f32 position[3];
    Vec3fArray *unk34;
    f32 timeDelta;
    f32 unk3C; // raised sound timer?
    BKVertexList *vertexList1;
    BKVertexList *vertexList2;
    u8 hasMetPlayer;
    u8 unk49;
    //u8 pad4A[2];
    f32 unk4C; // timer?
    s32 unk50; // related to unk4C & unk54
    f32 unk54; // timer?
} maClanker;

enum maClankerState_e {
    MACLANKER_STATE_0_NOT_INITIALIZED,
    MACLANKER_STATE_1_IDLE_UNDERWATER,
    MACLANKER_STATE_2_LIFTING,
    MACLANKER_STATE_3_IDLE_RAISED
};

BKCollisionTriangle *__maClanker_getClankerCollisionTris(f32 arg0[3], f32 arg1[3], f32 arg2[3], u32 arg3){ // [port] pointer-width args
    BKCollisionTriangle *collision_tris;

    collision_tris = collisionList_intersectLineGlobal(maClanker.collisionList, maClanker.vertexList1, maClanker.position, 0, 1.0f, arg0, arg1, arg2, arg3);
    if(collision_tris && func_8029453C()){
        func_80340200(maClanker.unk18, maClanker.position, 0, 1.0f, 0, collision_tris->unk0, maClanker.vertexList1, arg1);
    }
    return collision_tris;
}

void __code1F70_func_80388428(f32 arg0[3], f32 arg1[3], f32 arg2, f32 arg3[3], s32 arg4, u32 arg5){ // [port] pointer-width args
    collisionList_intersectMovingSphereGlobal(maClanker.collisionList, maClanker.vertexList1, maClanker.position, 0, 1.0f, arg0, arg1, arg2, arg3, arg4, arg5);
}

void func_803884A8(f32 arg0[3], f32 arg1, f32 arg2[3], u32 arg3){ // [port] pointer-width args
    collisionList_intersectSphereGlobal(maClanker.collisionList, maClanker.vertexList1, maClanker.position, 0, 1.0f, arg0, arg1, arg2, arg3);
}

void maClanker_setState(s32 next_state){
    s32 current_state;
    if(maClanker.currentState == MACLANKER_STATE_2_LIFTING){
        sfxSource_triggerCallbackByIndex(maClanker.sfxsourceIdx);
        func_8030E760(SFX_7F_HEAVYDOOR_SLAM, 0.6f, 20000);
        func_8030E760(SFX_7F_HEAVYDOOR_SLAM, 0.8f, 20000);
        func_8030E760(SFX_7F_HEAVYDOOR_SLAM, 0.9f, 20000);
        func_8030E760(SFX_7F_HEAVYDOOR_SLAM, 1.0f, 20000);
    }//L80388594
    current_state = maClanker.currentState;
    maClanker.currentState = next_state;
    maClanker.timeDelta = 0.0f;
    if(maClanker.currentState == MACLANKER_STATE_1_IDLE_UNDERWATER){
        skeletalAnim_set(maClanker.skeletonAnim, ASSET_C3_ANIM_CLANKER_IDLE, 0.0f, 10.0f);
    }
    if(maClanker.currentState == MACLANKER_STATE_2_LIFTING){
        func_8030DD90(maClanker.sfxsourceIdx, 0);
        sfxsource_playSfxAtVolume(maClanker.sfxsourceIdx, 1.0f);
        sfxsource_setSfxId(maClanker.sfxsourceIdx, SFX_7D_ANCHOR_LIFTING);
        sfxSource_setunk43_7ByIndex(maClanker.sfxsourceIdx, 3);
        sfxsource_setSampleRate(maClanker.sfxsourceIdx, 27000);
        sfxSource_func_8030E2C4(maClanker.sfxsourceIdx);
    }

    if(maClanker.currentState == MACLANKER_STATE_3_IDLE_RAISED){
        if(current_state != MACLANKER_STATE_2_LIFTING){
            skeletalAnim_set(maClanker.skeletonAnim, ASSET_C3_ANIM_CLANKER_IDLE, 0.0f, 10.0f);
        }
        maClanker.position[1] = 1100.0f;
    }
}

void maClanker_spawnJiggy(void) {
    jiggy_spawn(JIGGY_17_CC_CLANKER_RAISED, maClankerJiggyPosition);
}

void maClanker_raiseClankerCutscene(void) {
    func_80324E38(0, 3);
    timed_setStaticCameraToNode(0, 0);
    timed_setStaticCameraToNode(5.5f, 1);
    timed_setStaticCameraToNode(7.0f, 2);
    timed_setStaticCameraToNode(12.5f, 3);
    timedFunc_set_0(13.0f, &maClanker_spawnJiggy);
    timed_setStaticCameraToNode(16.0f, 1);
    if (jiggyscore_isCollected(JIGGY_17_CC_CLANKER_RAISED) == FALSE) {
        func_80324DBC(18.0f, VER_SELECT(ASSET_D2C_DIALOG_CLANKER_KEY_COMPLETE, 0x9FF, 0, 0), 4, NULL, NULL, NULL, 0);
    }
    timed_exitStaticCamera(18.0f);
    func_80324E38(18.0f, 0);
}


void maClanker_draw(Gfx **gfx, Mtx **mtx, Vtx **vtx){
    BKVertexList *tmp_vertex_list;
    BoneTransformList *bone_transform_list;
    f32 player_position[3];
    f32 viewport_position[3];
    int i;
    s32 tmp_s0;
    f32 sp84[3];
    s32 pad80;
    f32 sp74[3];
    f32 sp68[3];
    f32 sp5C[3];
    

    if(maClanker.currentState == MACLANKER_STATE_0_NOT_INITIALIZED)
        return;
    
    viewport_getPosition_vec3f(viewport_position);
        
    if(viewport_position[0] <  -2600.0f || 11600.0f < viewport_position[0])
        return;

    bone_transform_list = skeletalAnim_getBoneTransformList(maClanker.skeletonAnim);
    boneTransformList_getBoneScale(bone_transform_list, 0x40, sp84);
    for( i = 0; i < 3; i++){
        sp84[i] = sp84[i] + (1.3 - sp84[i]) * maClanker.unk8;
    }

    boneTransformList_setBoneScale(bone_transform_list, 0x40, sp84);

    if(maClanker.currentState == MACLANKER_STATE_1_IDLE_UNDERWATER){
        func_8033A9A8(bone_transform_list, 0x44, D_80389C0C);
        func_8033A9A8(bone_transform_list, 0x45, D_80389C0C);
        func_8033A9A8(bone_transform_list, 0x46, D_80389C0C);

        func_8033A9A8(bone_transform_list, 0x47, D_80389C18);
        func_8033A9A8(bone_transform_list, 0x48, D_80389C18);
        func_8033A9A8(bone_transform_list, 0x49, D_80389C18);
    }

    player_getPosition(player_position);

    for(i = 0; i < 2; i++){//L803888FC
        vec3fArray_get_vec3f(maClanker.unk34, (i == 0) ? 0x10 : 0xf, sp74);
        sp68[0] = player_position[0] - sp74[0];
        sp68[1] = player_position[1] - sp74[1];
        sp68[2] = player_position[2] - sp74[2];
        ml_vec3f_normalize(sp68);

        sp5C[0] = 0.0f;
        sp5C[1] = sp68[2] * 45.0f;
        sp5C[2] = -sp68[1] * 45.0f;
        func_8033A9A8(bone_transform_list, (i == 0) ? 0x42 : 0x43, sp5C);
    }
    tmp_vertex_list = maClanker.vertexList1;
    maClanker.vertexList1 = maClanker.vertexList2;
    maClanker.vertexList2 = tmp_vertex_list;

    modelRender_setAppendageVisibility(1, (maClanker.currentState == MACLANKER_STATE_3_IDLE_RAISED) ? 1 : 0);
    tmp_s0 = (viewport_position[0] < 100.0f)? 0 : 1;
    modelRender_setAppendageVisibility(2, 1);
    modelRender_setAppendageVisibility(3, 1);
    modelRender_setAppendageVisibility(4, tmp_s0);
    modelRender_setAppendageVisibility(5, tmp_s0);
    modelRender_setAppendageVisibility(6, tmp_s0);
    modelRender_setAppendageVisibility(7, tmp_s0);
    modelRender_setAppendageVisibility(8, tmp_s0);
    if(tmp_s0){
        tmp_s0 = (s32)(maClanker.unk4C * 3.99 + 1.0);
        modelRender_setAppendageVisibility(2, tmp_s0);
        modelRender_setAppendageVisibility(3, tmp_s0);
    }
    modelRender_setBoneTransformList(bone_transform_list);
    modelRender_setRefPoints(maClanker.unk34);
    modelRender_setVertexList(maClanker.vertexList1);
    modelRender_setDepthMode(MODEL_RENDER_DEPTH_FULL);
    modelRender_draw(gfx, mtx, maClanker.position, NULL, 1.0f, NULL, maClanker.model);
    if(func_80340020(maClanker.unk18, maClanker.position, 0, 1.0f, 0, maClanker.vertexList1, player_position, player_position)){
        func_8028FAB0(player_position);
        baModel_802921D4(player_position);
    }
}

void func_80388B4C(f32 arg0[3]) { // [port] pointer-width
    vec3fArray_get_vec3f(maClanker.unk34, 5, arg0);
}

void func_80388B78(f32 arg0[3], f32 arg1[3]){
    vec3fArray_get_vec3f(maClanker.unk34, 7, arg0);
    vec3fArray_get_vec3f(maClanker.unk34, 8, arg1);
}

void func_80388BBC(f32 arg0[3], f32 arg1[3]){
    vec3fArray_get_vec3f(maClanker.unk34, 9, arg0);
    vec3fArray_get_vec3f(maClanker.unk34, 10, arg1);
}

void func_80388C00(NodeProp *arg0, ActorMarker *arg1){ // [port] pointer-width
    func_8031CD20(arg0, MAP_B_CC_CLANKERS_CAVERN, WARP_CC_3_RIGHT_GILLS);
}

void func_80388C28(NodeProp *arg0, ActorMarker *arg1){ // [port] pointer-width
    func_8031CD20(arg0, MAP_B_CC_CLANKERS_CAVERN, WARP_CC_4_LEFT_GILLS);
}

void func_80388C50(NodeProp *arg0, ActorMarker *arg1){ // [port] pointer-width
    func_8031CD20(arg0, MAP_B_CC_CLANKERS_CAVERN, WARP_CC_1_RIGHT_TOOTH);
}

void CC_func_80388C78(NodeProp *arg0, ActorMarker *arg1){ // [port] pointer-width
    func_8031CD20(arg0, MAP_B_CC_CLANKERS_CAVERN, WARP_CC_2_LEFT_TOOTH);
}

int CC_func_80388CA0(void){
    return maClanker.currentState == MACLANKER_STATE_3_IDLE_RAISED;
}

void maClanker_release(void){
    if(maClanker.currentState){
        skeletalAnim_free(maClanker.skeletonAnim);
        sfxsource_freeSfxsourceByIndex(maClanker.sfxsourceIdx);
        func_80340690(maClanker.unk18);
        vec3fArray_free(maClanker.unk34);
        if(modelbin_getVtxList(maClanker.model) != maClanker.vertexList1)
            vtxList_free(maClanker.vertexList1);
        if(modelbin_getVtxList(maClanker.model) != maClanker.vertexList2)
            vtxList_free(maClanker.vertexList2);
        assetcache_release((void *)maClanker.model);
        maClanker.unk34 = NULL;
        maClanker.skeletonAnim = NULL;
        maClanker.unk18 = NULL;
    }
}

void maClanker_init(void){
    maClanker.currentState = MACLANKER_STATE_0_NOT_INITIALIZED;
    if(gsworld_getMap() == MAP_B_CC_CLANKERS_CAVERN){
        maClanker.skeletonAnim = skeletalAnim_new();
        maClanker.sfxsourceIdx = sfxsource_createSfxsourceAndReturnIndex();
        maClanker.unk8 = 1.0f;
        maClanker.unk18 = func_803406B0();
        maClanker.currentState = MACLANKER_STATE_0_NOT_INITIALIZED;
        maClanker.model = assetcache_get(ASSET_88E_MODEL_CLANKER_CHAIN);
        maClanker.collisionList = modelbin_getCollisionList(maClanker.model);
        maClanker.unk34 = vec3fArray_new();
        maClanker.unk3C = 1.0f;
        maClanker.vertexList1 = modelbin_getVtxList(maClanker.model);
        maClanker.vertexList2 = vtxList_clone(maClanker.vertexList1);
        maClanker.hasMetPlayer = FALSE;
        maClanker.unk49 = 0;
        maClanker.unk50 = 0;
        maClanker.unk4C = 0.0f;
        maClanker.unk54 = 1.0f;
        maClanker.position[0] = 5500.0f;
        maClanker.position[2] = 0.0f;
        maClanker.position[1] = 0.0f;
        func_80320B24(__maClanker_getClankerCollisionTris, __code1F70_func_80388428, func_803884A8);
        if(!nodeProp_findPositionFromActorId(ACTOR_3B_CLANKER_DIALOG_TRIGGER, maClanker.meetDialogPosition)){
            maClanker.meetDialogPosition[0] =  0.0f;
            maClanker.meetDialogPosition[1] = -1e+06f;
            maClanker.meetDialogPosition[2] =  0.0f;
        }
        if(jiggyscore_isSpawned(JIGGY_17_CC_CLANKER_RAISED)){
            maClanker_setState(MACLANKER_STATE_3_IDLE_RAISED);
        }
        else{
            maClanker_setState(MACLANKER_STATE_1_IDLE_UNDERWATER);
        }
    }
}

void maClanker_raiseClanker(void){
    if(maClanker.currentState == MACLANKER_STATE_1_IDLE_UNDERWATER){
        maClanker_setState(MACLANKER_STATE_2_LIFTING);
    }
}

void maClanker_playScrewNoise(s32 arg0){
    f32 sp1C[3];
    vec3fArray_get_vec3f(maClanker.unk34, 5, sp1C);
    if(arg0 != 0){
        sfx_playFadeShorthandDefault(SFX_91_METALLIC_SOUND, 0.7f, 32675, sp1C, 100, 6000);
    }
    else{
        sfx_playFadeShorthandDefault(SFX_82_METAL_BREAK, 0.9f, 24000, sp1C, 100, 6000);
    }
    maClanker.unk8 = 1.0f;
}

void maClanker_update(void){
    f32 player_position[3];
    f32 time_delta = time_getDelta();
    f32 sp64;
    f32 sp60;
    f32 sp54[3];
    f32 sp48[3];
    BKCollisionTriangle *tmp_v0;
    f32 pad[3];

    code13C0_checkCCChecksums();
    if(maClanker.currentState != MACLANKER_STATE_0_NOT_INITIALIZED && gsworld_getUnk0() == 2){
        // Anchor: teammate raised Clanker — play the physical raise (no cutscene).
        if(maClanker.currentState == MACLANKER_STATE_1_IDLE_UNDERWATER && jiggyscore_isSpawned(JIGGY_17_CC_CLANKER_RAISED)){
            maClanker_raiseClanker();
        }
        player_getPosition(player_position);
        maClanker.triggerMeetDialog = (ml_vec3f_distance(player_position, maClanker.meetDialogPosition) < 200.0f);

        maClanker.timeDelta += time_delta;
        sp64 = skeletalAnim_getProgress(maClanker.skeletonAnim);
        skeletalAnim_update(maClanker.skeletonAnim, time_delta, 1);
        sp60 = skeletalAnim_getProgress(maClanker.skeletonAnim);
        if(maClanker.currentState == MACLANKER_STATE_3_IDLE_RAISED){
            vec3fArray_get_vec3f(maClanker.unk34, 5, sp54);
            if(sp60 < sp64){
                sfx_playFadeShorthandDefault(SFX_7E_CREAKY_DOOR_OPENING, 0.6f, 32300, sp54, 1000, 5000);
            }//L80389058

            if(sp64 < 0.3 && 0.3 <= sp60){
                sfx_playFadeShorthandDefault(SFX_7E_CREAKY_DOOR_OPENING, 0.5f, 32300, sp54, 1000, 5000);
            }
        }//L8038909C

        if(maClanker.currentState == MACLANKER_STATE_2_LIFTING){
            maClanker.position[1] += 100.0f * time_delta;
        }

        if(0.0f < maClanker.unk8){
            maClanker.unk8 -= time_delta / 2;
            if(maClanker.unk8 <= 0.0f)
                maClanker.unk8 = 0.0f;
        }

        if(maClanker.currentState == MACLANKER_STATE_1_IDLE_UNDERWATER){
            if(maClanker.triggerMeetDialog && skeletalAnim_getAnimId(maClanker.skeletonAnim) != ASSET_C4_ANIM_CLANKER_BITE){
                skeletalAnim_set(maClanker.skeletonAnim, ASSET_C4_ANIM_CLANKER_BITE, 1.0f, 10.0f);
                if(!maClanker.hasMetPlayer){
                    gcdialog_showDialog(VER_SELECT(ASSET_D2B_DIALOG_CLANKER_MEET, 0x9FE, 0, 0), 0xE, maClanker.position, NULL, NULL, NULL);
                    maClanker.hasMetPlayer = TRUE;
                }
            }//L8038918C
            
            if(!maClanker.triggerMeetDialog && skeletalAnim_getAnimId(maClanker.skeletonAnim) == ASSET_C4_ANIM_CLANKER_BITE){
                skeletalAnim_set(maClanker.skeletonAnim, ASSET_C3_ANIM_CLANKER_IDLE, 1.0f, 10.0f);
            }
        }//L803891BC

        if(maClanker.currentState == MACLANKER_STATE_2_LIFTING){
            func_803114D0();
            if(1100.0f <= maClanker.position[1]){
                maClanker_setState(MACLANKER_STATE_3_IDLE_RAISED);
            }
        }//L803891F8

        if(maClanker.currentState == MACLANKER_STATE_3_IDLE_RAISED){
            vec3fArray_get_vec3f(maClanker.unk34, 6, sp48);
            if(ml_vec3f_distance(sp48, player_position) <= 130.0f && player_position[1] - sp48[1] < 50.0f){
                func_8031D04C(MAP_21_CC_WITCH_SWITCH_ROOM, WARP_CC_WITCH_SWITCH_1_TOP_ENTRANCE);
            }
        }//L80389260

        if( maClanker.currentState == MACLANKER_STATE_3_IDLE_RAISED){
            tmp_v0 = func_8028EF48();
            if( tmp_v0 && !maClanker.unk49
            ){
                if(tmp_v0->flags & 2){
                    func_8031CE28(0x22, 5, 180.0f);
                    maClanker.unk49++;
                }
                else if(tmp_v0->flags & 4){
                    func_8031CE28(0x22, 4, 0.0f);
                    maClanker.unk49++;
                }
            }
        }//L803892DC
        if(ml_timer_update(&maClanker.unk3C, time_delta)){
            if(maClanker.currentState == MACLANKER_STATE_3_IDLE_RAISED){
                func_8030E9FC(SFX_D0_GRIMLET_SQUEAK, 0.5f, 0.7f, 20000, maClankerRaisedSoundPosition, 2000.0f, 4000.0f);
            }else{
                func_8030EA54(SFX_D0_GRIMLET_SQUEAK, 0.5f, 0.7f, 20000, maClankerRaisedSoundPosition, 2000.0f, 4000.0f);
            }//L80389384
            maClanker.unk3C = randf2(3.0f, 6.0f);
        }//L803893A0
        if(maClanker.unk50 == 0){
            if(ml_timer_update(&maClanker.unk54, time_delta))
                maClanker.unk50 = 1;
        }

        if(maClanker.unk50){
            maClanker.unk4C += maClanker.unk50 * ((time_delta * 30.0) / 4);
            if(1.0f < maClanker.unk4C){
                maClanker.unk50 = -1;
                maClanker.unk4C = 1.0f;
            }
            else if(maClanker.unk4C < 0.0f){
                maClanker.unk50 = 0;
                maClanker.unk4C = 0.0f;
                maClanker.unk54 = randf2(0.1f, 7.0f);
            }
        }
    }//L80389490

}

void maClanker_defrag(void){
    if(maClanker.unk34)
        maClanker.unk34 = vec3fArray_defrag(maClanker.unk34);
    
    if(maClanker.skeletonAnim)
        maClanker.skeletonAnim =  defrag(maClanker.skeletonAnim);

    if(maClanker.unk18)
        maClanker.unk18 = func_803406D4(maClanker.unk18);
}