/**
 * d_a_alink_bow.inc
 * Player Bow and Arrow action handling
 */

#include "d/actor/d_a_alink.h"
#include "d/d_com_inf_game.h"
#include "d/actor/d_a_arrow.h"
#include "d/actor/d_a_horse.h"

void daAlink_c::getArrowFlyData(f32* o_distance, f32* o_speed, BOOL i_forceCharge) const {
    if (mEquipItem == dItemNo_PACHINKO_e) {
        *o_distance = mpHIO->mItem.mBow.m.mSlingshotDistance;
        *o_speed = mpHIO->mItem.mBow.m.mSlingshotSpeed;
    } else if (dComIfGp_checkPlayerStatus0(0, 0x200000)) {
        *o_distance = mpHIO->mItem.mBow.m.mScopeArrowDistance;
        *o_speed = mpHIO->mItem.mBow.m.mScopeArrowSpeed;
    } else if (field_0x301c == 0 || i_forceCharge) {
        if (field_0x301e == 1) {
            *o_distance = mpHIO->mItem.mBow.m.mChargeBombArrowDistance;
            *o_speed = mpHIO->mItem.mBow.m.mChargeBombArrowSpeed;
        } else {
            *o_distance = mpHIO->mItem.mBow.m.mChargeArrowDistance;
            *o_speed = mpHIO->mItem.mBow.m.mChargeArrowSpeed;
        }
    } else if (field_0x301e == 1) {
        *o_distance = mpHIO->mItem.mBow.m.mBombArrowDistance;
        *o_speed = mpHIO->mItem.mBow.m.mBombArrowSpeed;
    } else {
        *o_distance = mpHIO->mItem.mBow.m.mArrowDistance;
        *o_speed = mpHIO->mItem.mBow.m.mArrowSpeed;
    }
}

f32 daAlink_c::getArrowIncAtR() const {
    return mpHIO->mItem.mBow.m.mArrowAttackRadius;
}

s16 daAlink_c::getBombArrowFlyExplodeTime() const {
    return mpHIO->mItem.mBow.m.mBombArrowFlyExplodeTime;
}

f32 daAlink_c::getArrowIncAtMaxStart() const {
    return mpHIO->mItem.mBow.m.mArrowIncAttackMaxStart;
}

f32 daAlink_c::getArrowIncAtMax() const {
    return mpHIO->mItem.mBow.m.mArrowIncAttackMax;
}

BOOL daAlink_c::checkBowAndSlingItem(int i_itemNo) {
    return checkBowItem(i_itemNo) || i_itemNo == dItemNo_PACHINKO_e;
}

void daAlink_c::setSlingModel() {
    J3DAnmTransform* bck = (J3DAnmTransform*)mAnmHeap9.loadDataIdx(dRes_ID_ALANM_BCK_PWAIT_e);
    JKRHeap* prev_heap = setItemHeap();

    mHeldItemModel = initModel(loadAramBmd(dRes_ID_ALANM_BMD_AL_PACHI_e, 0x2C00), 0);
    
    if (!mItemBck.init(bck, FALSE, J3DFrameCtrl::EMode_LOOP, 1.0f, 0, -1, false)) {
        JUT_ASSERT(108, 0);
    }

    mDoExt_setCurrentHeap(prev_heap);
    field_0x2f95 = 5;
    field_0x2f94 = 103;
}

cXyz* daAlink_c::checkBowCameraArrowPosP(s16* o_angleX, s16* o_angleY) {
    if (!checkBowAnime() || mEquipItem == dItemNo_PACHINKO_e) {
        return NULL;
    }

    s16 angle_y;
    if (checkHorseRide() && checkBoarSingleBattle() && dComIfGp_getHorseActor() != NULL) {
        angle_y = dComIfGp_getHorseActor()->shape_angle.y;
    } else if (checkMagneBootsOn()) {
        angle_y = field_0x3118;
    } else {
        angle_y = shape_angle.y;
    }

    angle_y += mBodyAngle.y;

    mDoMtx_stack_c::transS(field_0x3834);
    concatMagneBootMtx();
    mDoMtx_stack_c::ZXYrotM(mBodyAngle.x, angle_y, 0);

    static const Vec localPos = {3.45f, 45.32f, -7.0f};
    mDoMtx_stack_c::multVec(&localPos, &mHeldItemRootPos);

    *o_angleX = mBodyAngle.x;
    *o_angleY = angle_y;
    return &mHeldItemRootPos;
}

bool daAlink_c::checkArrowChargeEnd() const {
    return checkBowChargeWaitAnime() && field_0x301c == 0;
}

BOOL daAlink_c::checkBowReadyAnime() const {
    return checkBowReloadAnime() || checkBowChargeWaitAnime() || checkBowWaitAnime();
}

BOOL daAlink_c::checkBowAnime() const {
    return checkBowReadyAnime() || checkBowShootAnime();
}

void daAlink_c::makeArrow() {
    if (dComIfGs_getArrowNum() != 0) {
        if (field_0x301e == 1 && dComIfGp_getSelectItemNum(mSelectItemId) == 0) {
            field_0x301e = 0;
        }

        mItemAcKeep.setData(daArrow_c::makeArrow(this, field_0x301e));

        if (mItemAcKeep.getActor() == NULL) {
            // "Not enough memory to create item!!"
            OS_REPORT("メモリが足りなくてアイテム発生できません！！\n");
            JUT_ASSERT(221, 0);
        }
    }

    mItemVar0.field_0x3018 = 0;
}

void daAlink_c::deleteArrow() {
    daArrow_c* arrow_p = (daArrow_c*)mItemAcKeep.getActor();

    if (arrow_p != NULL && fopAcM_GetName(arrow_p) == fpcNm_ARROW_e) {
        if (arrow_p->checkBombArrow() &&
            (mDamageTimer == mpHIO->mDamage.m.mInvincibleTime || checkModeFlg(8)))
        {
            arrow_p->setBombArrowExplode();
            dComIfGp_addSelectItemNum(mSelectItemId, -1);
            dComIfGp_setItemArrowNumCount(-1);
        } else {
            fopAcM_delete(arrow_p);
        }
        mItemAcKeep.clearData();
    }
}

void daAlink_c::setBowOrSlingStatus() {
    if (mEquipItem == dItemNo_PACHINKO_e) {
        dComIfGp_setPlayerStatus0(0, 0x40);
    } else {
        dComIfGp_setPlayerStatus0(0, 0x1000);
    }
}

void daAlink_c::changeArrowType() {
    if (checkCanoeSlider() || (mEquipItem == dItemNo_BOW_e && field_0x301e == 0) ||
        (mEquipItem == dItemNo_BOMB_ARROW_e && field_0x301e == 0 &&
         dComIfGp_getSelectItemNum(mSelectItemId) == 0) ||
        (mEquipItem == dItemNo_HAWK_ARROW_e && checkAttentionLock()))
    {
        return;
    }

    setItemActionButtonStatus(BUTTON_STATUS_SWITCH);

    if (arrowChangeTrigger()) {
        if (mEquipItem == dItemNo_HAWK_ARROW_e) {
            if (dComIfGp_checkPlayerStatus0(0, 0x200000)) {
                dComIfGp_clearPlayerStatus0(0, 0x200000);
                seStartSystem(Z2SE_AL_HAWK_EYE_PUTOFF);
            } else {
                dComIfGp_setPlayerStatus0(0, 0x200000);
                seStartSystem(Z2SE_AL_HAWK_EYE_PUTON);
            }
        } else {
            if (field_0x301e == 1) {
                field_0x301e = 0;
            } else {
                field_0x301e = 1;
            }

            if (mItemAcKeep.getActor() != NULL) {
                deleteArrow();
                makeArrow();
                setBowReloadAnime();
            }
        }
    }
}

BOOL daAlink_c::cancelBowMoveRideNotAtn() {
    return checkModeFlg(0x400) && checkAttentionLock() && mTargetedActor == NULL;
}

BOOL daAlink_c::cancelBowMove() {
    if (mTargetedActor == NULL && !checkAttentionLock() && mFastShotTime == 0 &&
        !checkBowReadyAnime() && (!checkBowShootAnime() || checkAnmEnd(&mUpperFrameCtrl[2])))
    {
        resetUpperAnime(UPPER_2, -1.0f);
        return true;
    }

    return false;
}

void daAlink_c::setBowReadyAnime() {
    if (!checkBowAnime()) {
        if (mEquipItem == dItemNo_BOMB_ARROW_e) {
            if (dComIfGp_getSelectItemNum(mSelectItemId) != 0) {
                field_0x301e = 1;
            } else {
                field_0x301e = 0;
            }
        } else {
            field_0x301e = 0;
        }
    }

    setUpperAnimeBase(dRes_ID_ALANM_BCK_ASHOOTWAIT_e);

    if (checkResetFlg0(RFLG0_UNK_80)) {
        mItemMode = 0;
    } else {
        mItemMode = 3;
    }

    field_0x2f97 = 5;
    field_0x2f96 = 4;

    if (mEquipItem == dItemNo_PACHINKO_e) {
        changeItemBck(dRes_ID_ALANM_BCK_PSHOOT_e, -1.0f);
    } else {
        changeItemBck(dRes_ID_ALANM_BCK_BASHOOT_e, -1.0f);
    }
}

void daAlink_c::setBowReloadAnime() {
    setUpperAnimeParam(dRes_ID_ALANM_BCK_ARELORD_e, UPPER_2, &mpHIO->mItem.mBow.m.mLoadAnm);
    setFacePriTexture(FTANM_FINISHA);
    setFacePriBck(dRes_ID_ALANM_BCK_FARELORD_e);

    if (mEquipItem == dItemNo_PACHINKO_e) {
        changeItemBck(dRes_ID_ALANM_BCK_PRELORD_e, mpHIO->mItem.mBow.m.mLoadAnm.mStartFrame);
        field_0x2f97 = 5;
        seStartOnlyReverb(Z2SE_AL_PACHINKO_DRAW);
    } else {
        changeItemBck(dRes_ID_ALANM_BCK_BARELORD_e, mpHIO->mItem.mBow.m.mLoadAnm.mStartFrame);
        field_0x2f97 = 7;
        seStartOnlyReverb(Z2SE_AL_DRAW_BOW);
    }

    field_0x2f96 = 0;
    field_0x301c = mpHIO->mItem.mBow.m.mChargeArrowTime;
}

BOOL daAlink_c::checkUpperItemActionBow() {
    daPy_frameCtrl_c* frameCtrl_p = &mUpperFrameCtrl[2];

    if (mEquipItem == dItemNo_PACHINKO_e) {
        static const Vec slingLocalPos = {10.0f, 10.0f, 0.0f};
        mDoMtx_multVec(getLeftItemMatrix(), &slingLocalPos, &mHeldItemRootPos);
    }

    if (checkBowChargeWaitAnime()) {
        daArrow_c* arrow_p = (daArrow_c*)mItemAcKeep.getActor();

        if (mEquipItem != dItemNo_PACHINKO_e) {
            if (field_0x301c > 0) {
                field_0x301c--;

                if (field_0x301c <= frameCtrl_p->getEnd() && frameCtrl_p->getFrame() < 0.1f &&
                    frameCtrl_p->getRate() < 0.1f)
                {
                    frameCtrl_p->setRate(1.0f);
                }
            } else {
                onResetFlg0(RFLG0_UNK_10);
                cancelItemUseQuake(0);
            }
        }

        if (checkReadyItem()) {
            if (mItemVar0.field_0x3018 != 0) {
                setUpperAnimeParam(dRes_ID_ALANM_BCK_ASHOOT_e, UPPER_2, &mpHIO->mItem.mBow.m.mShootAnm);
                setFacePriBck(dRes_ID_ALANM_BCK_FAT_e);
                field_0x2f96 = 0;

                u16 bck_res_id;
                if (mEquipItem == dItemNo_PACHINKO_e) {
                    bck_res_id = dRes_ID_ALANM_BCK_PSHOOT_e;
                    if (dComIfGs_getPachinkoNum() != 0 &&
                        daArrow_c::makeSlingStone(this, &mHeldItemRootPos) != NULL)
                    {
                        dComIfGp_setItemPachinkoNumCount(-1);
                    }
                } else if (field_0x301c != 0) {
                    bck_res_id = dRes_ID_ALANM_BCK_BASHOOT_e;
                } else {
                    bck_res_id = dRes_ID_ALANM_BCK_BASHOOTTAME_e;
                }

                changeItemBck(bck_res_id, mpHIO->mItem.mBow.m.mShootAnm.mStartFrame);
                mItemVar0.field_0x3018 = 0;
            } else if (mEquipItem == dItemNo_PACHINKO_e) {
                if (!itemButton()) {
                    dComIfGp_getVibration().StartShock(VIBMODE_S_POWER1, 1, cXyz(0.0f, 1.0f, 0.0f));
                    seStartOnlyReverb(Z2SE_AL_PACHINKO_SHOT);
                    mItemVar0.field_0x3018 = 1;
                    resetFacePriAnime();
                }
            } else if (!itemButton()) {
                if (arrow_p != NULL) {
                    u32 sound;
                    int vibmode;

                    if (field_0x301c != 0) {
                        arrow_p->setShoot();
                        vibmode = VIBMODE_S_POWER1;

                        if (arrow_p->checkBombArrow()) {
                            sound = Z2SE_OBJ_ARROWBOMB_SHOT;
                        } else {
                            sound = Z2SE_OBJ_ARROW_SHOT_NORMAL;
                        }
                    } else {
                        arrow_p->setChargeShoot();
                        vibmode = VIBMODE_S_POWER2;

                        if (arrow_p->checkBombArrow()) {
                            sound = Z2SE_OBJ_ARROWBOMB_SHOTGAIN;
                        } else {
                            sound = Z2SE_OBJ_ARROW_SHOT_GAIN;
                        }
                    }

                    dComIfGp_getVibration().StartShock(vibmode, 1, cXyz(0.0f, 1.0f, 0.0f));
                    seStartOnlyReverb(sound);

                    if (field_0x301e == 1) {
                        dComIfGp_addSelectItemNum(mSelectItemId, -1);
                    }

                    dComIfGp_setItemArrowNumCount(-1);
                    mItemAcKeep.clearData();
                    onResetFlg0(RFLG0_UNK_20000000);
                    field_0x30a4 = mpHIO->mItem.mBow.m.mBombArrowHoldTime;
                } else {
                    seStartOnlyReverb(Z2SE_AL_ARROW_EMPTY);
                }

                mItemVar0.field_0x3018 = 1;
                resetFacePriAnime();

                if (mEquipItem == dItemNo_BOW_e) {
                    field_0x301e = 0;
                }
                (void)0;
            } else {
                changeArrowType();
            }
        }
    } else if (checkBowReloadAnime()) {
        if (checkAnmEnd(frameCtrl_p)) {
            setUpperAnimeBaseSpeed(dRes_ID_ALANM_BCK_ARELORDTAME_e, 0.0f, -1.0f);
            setFacePriTexture(FTANM_ARELORD);
            setFacePriBck(dRes_ID_ALANM_BCK_FARELORDTAME_e);

            if (mEquipItem != dItemNo_PACHINKO_e) {
                changeItemBck(dRes_ID_ALANM_BCK_BARELORDTAME_e, 0.0f);
                dComIfGp_getVibration().StartQuake(VIBMODE_Q_POWER1, 1, cXyz(0.0f, 1.0f, 0.0f));
                onNoResetFlg3(FLG3_UNK_4);
            }
        }
    } else if (checkBowWaitAnime()) {
        if ((mItemVar0.field_0x3018 == 0 && mFastShotTime != 0) ||
            (mItemMode == 0 && !itemButton() && mItemVar0.field_0x3018 == 0 &&
             cancelBowMoveRideNotAtn()))
        {
            resetUpperAnime(UPPER_2, 3.0f);
            dComIfGp_clearPlayerStatus0(0, 0x1040);
            return 1;
        }

        if (mItemMode == 0 && (itemButton() || mItemVar0.field_0x3018 != 0) && checkReadyItem() &&
            (field_0x30a4 == 0 || field_0x301e != 1))
        {
            setBowReloadAnime();

            if (mEquipItem == dItemNo_PACHINKO_e) {
                mItemVar0.field_0x3018 = 0;
            } else {
                makeArrow();
            }
        } else if (mEquipItem == dItemNo_HAWK_ARROW_e) {
            changeArrowType();
        }

        if (mItemMode != 0) {
            mItemMode--;
        }
    } else if (checkBowShootAnime()) {
        if (mUpperFrameCtrl[2].getFrame() >= 6.0f) {
            field_0x2f97 = 5;
        } else if (mUpperFrameCtrl[2].getFrame() >= 1.0f) {
            field_0x2f96 = 4;
        }

        if (checkAnmEnd(&mUpperFrameCtrl[2]) && cancelBowMoveRideNotAtn()) {
            resetUpperAnime(UPPER_2, 3.0f);
            dComIfGp_clearPlayerStatus0(0, 0x1040);
            return 1;
        }

        if (checkAnmEnd(&mUpperFrameCtrl[2]) ||
            (mUpperFrameCtrl[2].getFrame() > mpHIO->mItem.mBow.m.mShootAnm.mCancelFrame &&
             itemButton()))
        {
            setBowReadyAnime();
        }

        if (mItemMode != 0) {
            mItemMode--;
        }
    }

    if (checkBowWaitAnime() || (mEquipItem == dItemNo_PACHINKO_e && checkBowChargeWaitAnime())) {
        field_0x33dc += mpHIO->mItem.mBow.m.mShootAnm.mSpeed;
    } else {
        field_0x33dc = mUpperFrameCtrl[2].getFrame();
    }

    return cancelUpperItemReadyAnime(0);
}

void daAlink_c::checkUpperItemActionBowFly() {
    if (checkBowAnime()) {
        checkUpperItemActionBow();
        setBodyAngleXReadyAnime(0);
    } else if (checkReadyItem() && itemTrigger()) {
        setBowReadyAnime();
        mItemMode = 0;
    }
}

int daAlink_c::checkNextActionBow() {
    if (mFastShotTime != 0 && checkBowReadyAnime()) {
        mFastShotTime--;
    }

    BOOL is_hawk_arrow = false;
    if (!checkBowAnime()) {
        setBowReadyAnime();
        setFastShotTimer();

        if (!checkAttentionLock()) {
            field_0x2fe4 = shape_angle.y;
        }

        mItemMode = 0;
        mItemVar0.field_0x3018 = 1;

        if (mEquipItem == dItemNo_HAWK_ARROW_e) {
            is_hawk_arrow = true;
            mFastShotTime = 0;
        }

        if ((!checkAttentionLock() && !checkDashAnime()) || checkModeFlg(0x400)) {
            mFastShotTime = 0;

            if (checkAttentionLock() && checkModeFlg(0x400)) {
                mItemVar0.field_0x3018 = 1;
            } else {
                mItemVar0.field_0x3018 = 0;
            }

            if (!checkResetFlg0(RFLG0_UNK_80)) {
                mItemMode = 3;
            }
        }
    }

    BOOL rt = FALSE;
    if (!checkAttentionLock() && mFastShotTime == 0) {
        if (checkModeFlg(0x400)) {
            if (checkCanoeRide()) {
                rt = procCanoeBowSubjectInit();
            } else {
                rt = procHorseBowSubjectInit();
            }
        } else {
            rt = procBowSubjectInit();
        }
    } else {
        if (checkModeFlg(0x400)) {
            if (checkCanoeRide()) {
                rt = procCanoeBowMoveInit();
            } else {
                rt = procHorseBowMoveInit();
            }
        } else {
            rt = procBowMoveInit();
        }
    }

    if (rt && is_hawk_arrow) {
        dComIfGp_setPlayerStatus0(0, 0x200000);
        seStartSystem(Z2SE_AL_HAWK_EYE_PUTON);
    }

    return rt;
}

void daAlink_c::setBowModel() {
    J3DAnmTransform* bck = (J3DAnmTransform*)mAnmHeap9.loadDataIdx(dRes_ID_ALANM_BCK_BVJMPCL_e);
    JKRHeap* heap = setItemHeap();

    mHeldItemModel = initModel(loadAramBmd(dRes_ID_ALANM_BMD_AL_BOW_e, 0x4C00), 0);
    
    if (!mItemBck.init(bck, FALSE, 2, 1.0f, 0, -1, false)) {
        JUT_ASSERT(894, 0);
    }

    mDoExt_setCurrentHeap(heap);
    field_0x33dc = mItemBck.getBckAnm()->getFrameMax() - 0.001f;
    field_0x2f95 = 5;
    field_0x2f94 = 0x67;
}

bool daAlink_c::checkBowGrabLeftHand() const {
    return checkReinRide() && !checkBowAnime();
}

void daAlink_c::setBowHangAnime() {
    if (checkBowItem(mEquipItem)) {
        changeItemBck(dRes_ID_ALANM_BCK_BVJMPCH_e, 0.0f);
    }
}

void daAlink_c::setBowNormalAnime() {
    if (checkBowItem(mEquipItem)) {
        changeItemBck(dRes_ID_ALANM_BCK_BVJMPCL_e, -1.0f);
    } else if (mEquipItem == dItemNo_PACHINKO_e) {
        changeItemBck(dRes_ID_ALANM_BCK_PWAIT_e, -1.0f);
    }
}

void daAlink_c::setBowSight() {
    if (checkBowChargeWaitAnime() && !dComIfGp_checkPlayerStatus0(0, 0x200000)) {
        cXyz sight_pos;
        f32 dist;
        f32 speed;

        getArrowFlyData(&dist, &speed, TRUE);
        checkSightLine(dist, &sight_pos);
        mSight.setPos(&sight_pos);
        DUSK_IF_ELSE(dusk::getSettings().game.aimingReticle ? mSight.onDrawFlg() : mSight.offDrawFlg(), mSight.offDrawFlg());
    } else {
        mSight.offDrawFlg();
    }
}

int daAlink_c::procBowSubjectInit() {
    if (!commonProcInitNotSameProc(PROC_BOW_SUBJECT)) {
        return 0;
    }

    setSingleAnimeBaseSpeed(ANM_ATN_WAIT_RIGHT, 0.0f,
                            mpHIO->mItem.mBow.m.mStartInterpolation);
    mNormalSpeed = 0.0f;
    setBowOrSlingStatus();
    return 1;
}

int daAlink_c::procBowSubject() {
    setDoStatus(BUTTON_STATUS_BACK);
    if (!checkNextAction(0) && setBodyAngleToCamera()) {
        setBowSight();
    }

    return 1;
}

int daAlink_c::procBowMoveInit() {
    if (!commonProcInitNotSameProc(PROC_BOW_MOVE)) {
        return 0;
    }

    if (checkZeroSpeedF()) {
        onModeFlg(1);
    }

    setBlendAtnMoveAnime(mpHIO->mItem.mBow.m.mStartInterpolation);
    mProcVar2.field_0x300c = 0;
    setBowOrSlingStatus();
    return 1;
}

int daAlink_c::procBowMove() {
    cancelBowMove();

    if (mFastShotTime == 0 && mProcVar2.field_0x300c != 0 && checkBowWaitAnime() && !itemButton()) {
        resetUpperAnime(UPPER_2, -1.0f);
    }

    mProcVar2.field_0x300c = 1;
    onEndResetFlg0(ERFLG0_UNK_8000000);

    if (!checkNextAction(0)) {
        f32 morf = -1.0f;

        if (checkZeroSpeedF()) {
            onModeFlg(1);

            if (field_0x2f98 != 3) {
                field_0x2f98 = 3;
                morf = mpHIO->mBasic.m.mBasicInterpolation;
            }
            current.angle.y = shape_angle.y - 0x4000;
        } else {
            offModeFlg(1);
        }

        setBlendAtnMoveAnime(morf);
        setBodyAngleXReadyAnime(0);
    }

    return 1;
}
