// sl_walking_penguin.inc.c

struct SLWalkingPenguinStep {
    s32 stepLength;
    s32 anim;
    f32 speed;
    f32 animSpeed;
};

// The penguin follows a preset list of movements while walking forward.
struct SLWalkingPenguinStep sSLWalkingPenguinErraticSteps[] = {
    { 60, PENGUIN_ANIM_WALK, 6.0f,  1.0f }, // Walk forwards for 2 seconds
    { 30, PENGUIN_ANIM_IDLE, 0.0f,  1.0f }, // Stop for 1 second
    { 30, PENGUIN_ANIM_WALK, 12.0f, 2.0f }, // Walk forwards quickly for 1 second
    { 30, PENGUIN_ANIM_IDLE, 0.0f,  1.0f }, // Stop for 1 second
    { 30, PENGUIN_ANIM_WALK, -6.0f, 1.0f }, // Walk backwards for 1 second
    { 30, PENGUIN_ANIM_IDLE, 0.0f,  1.0f }, // Stop for 1 second
    { -1, 0, 0.0f,  0.0f }, // Repeat
};

static s32 sl_walking_penguin_turn(void) {
    // Stay still and use walking animation for the turn.
    o->oForwardVel = 0.0f;
    cur_obj_init_animation_with_accel_and_sound(PENGUIN_ANIM_WALK, 1.0f);

    // Turn around.
    o->oAngleVelYaw = 0x400;
    o->oMoveAngleYaw += o->oAngleVelYaw;

    if (o->oTimer == 31) {
        return TRUE; // Finished turning
    } else {
        return FALSE;
    }
}

void bhv_sl_walking_penguin_loop(void) {
    f32 adjustedXPos, adjustedZPos;
    f32 perpendicularOffset = 100.0f;

    o->oAngleVelYaw = 0;
    cur_obj_update_floor_and_walls();

    switch (o->oAction) {
        // Walk erratically across the ice bridge using preset steps.
        case SL_WALKING_PENGUIN_ACT_MOVING_FORWARDS:
            if (o->oTimer == 0) {
                // Initiate variables
                o->oSLWalkingPenguinCurStep = 0;
                o->oSLWalkingPenguinCurStepTimer = 0;
            }

            if (o->oSLWalkingPenguinCurStepTimer <
                sSLWalkingPenguinErraticSteps[o->oSLWalkingPenguinCurStep].stepLength) {
                o->oSLWalkingPenguinCurStepTimer++;
            } else {
                // Move to next step
                o->oSLWalkingPenguinCurStepTimer = 0;
                o->oSLWalkingPenguinCurStep++;
                if (sSLWalkingPenguinErraticSteps[o->oSLWalkingPenguinCurStep].stepLength < 0) {
                    // Reached the end of the list, go back to the start
                    o->oSLWalkingPenguinCurStep = 0;
                }
            }

            if (o->oPosX < 300.0f) {
                o->oAction++; // If reached the end of the bridge, turn around and head back.
            } else {
                // Move and animate the penguin
                o->oForwardVel = sSLWalkingPenguinErraticSteps[o->oSLWalkingPenguinCurStep].speed;

                cur_obj_init_animation_with_accel_and_sound(
                    sSLWalkingPenguinErraticSteps[o->oSLWalkingPenguinCurStep].anim,
                    sSLWalkingPenguinErraticSteps[o->oSLWalkingPenguinCurStep].animSpeed
                );
            }
            break;

        // At the end, turn around and prepare to head back across the bridge.
        case SL_WALKING_PENGUIN_ACT_TURNING_BACK:
            if (sl_walking_penguin_turn()) {
                o->oAction++; // Finished turning
            }
            break;

        // Walk back across the bridge at a constant speed.
        case SL_WALKING_PENGUIN_ACT_RETURNING:
            // Move and animate the penguin
            o->oForwardVel = 12.0f;
            cur_obj_init_animation_with_accel_and_sound(PENGUIN_ANIM_WALK, 2.0f);

            if (o->oPosX > 1700.0f) {
                o->oAction++; // If reached the start of the bridge, turn around.
            }
            break;

        // At the start, turn around and prepare to walk erratically across the bridge.
        case SL_WALKING_PENGUIN_ACT_TURNING_FORWARDS:
            if (sl_walking_penguin_turn()) {
                o->oAction = SL_WALKING_PENGUIN_ACT_MOVING_FORWARDS; // Finished turning
            }
            break;
    }

    cur_obj_move_standard(-78);
    if (!cur_obj_hide_if_mario_far_away_y(1000.0f)) {
        play_penguin_walking_sound(PENGUIN_WALK_BIG);
    }

    // Adjust the position to get a point better lined up with the visual model, for stopping the wind.
    // The new point is 60 units behind the penguin and 100 units perpedicularly, away from the snowman.

    adjustedXPos = o->oPosX + sins(0xDBB0) * 60.0f; // 0xDBB0 = -51 degrees, the angle the penguin is facing
    adjustedZPos = o->oPosZ + coss(0xDBB0) * 60.0f;
    adjustedXPos += perpendicularOffset * sins(0x1BB0); // 0x1BB0 = 39 degrees, perpendicular to the penguin
    adjustedZPos += perpendicularOffset * coss(0x1BB0);
    o->oSLWalkingPenguinWindCollisionXPos = adjustedXPos;
    o->oSLWalkingPenguinWindCollisionZPos = adjustedZPos;

    print_debug_bottom_up("x %d", o->oPosX);
    print_debug_bottom_up("z %d", o->oPosZ);
}
