import { RewardInfo } from "../rpc_client/types";
import { UserState } from "../rpc_client/accounts/UserState";
import { FarmState } from "../rpc_client/accounts/FarmState";
import Decimal from "decimal.js";
import { WAD } from "./utils";

export function calculatePendingRewards(
  farmState: FarmState,
  userState: UserState,
  rewardIndex: number,
  ts: Decimal,
): Decimal {
  const newRewardPerToken = calculateRewardPerStake(farmState, ts, rewardIndex);

  const newRewardTally = new Decimal(
    userState.activeStakeScaled.toString(),
  ).mul(newRewardPerToken);

  const newReward = newRewardTally.sub(
    new Decimal(userState.rewardsTallyScaled[rewardIndex].toString()),
  );

  return new Decimal(
    userState.rewardsIssuedUnclaimed[rewardIndex].toString(),
  ).add(newReward.div(WAD));
}

export function calculateCurrentRewardPerToken(
  farm: FarmState,
  rewardIndex: number,
  currentTimeUnit: Decimal,
): number {
  const rewardCurve = farm.rewardInfos[rewardIndex].rewardScheduleCurve;

  let index = 0;
  for (let i = 0; i < rewardCurve.points.length; i++) {
    if (
      new Decimal(rewardCurve.points[i].tsStart.toString()).lte(currentTimeUnit)
    ) {
      index = i;
    } else {
      break;
    }
  }

  return rewardCurve.points[index].rewardPerTimeUnit.toNumber();
}

function calculateRewardPerStake(
  farmState: FarmState,
  ts: Decimal,
  rewardIndex: number,
): Decimal {
  const rewardInfo = farmState.rewardInfos[rewardIndex];

  const tsDiff = ts.sub(new Decimal(rewardInfo.lastIssuanceTs.toString()));

  let rps = calculateCurrentRewardPerToken(farmState, rewardIndex, ts);
  const newRewards = Decimal.min(
    tsDiff.mul(new Decimal(rps)),
    new Decimal(rewardInfo.rewardsAvailable.toString()),
  );

  const rewardPerToken = new Decimal(
    rewardInfo.rewardPerShareScaled.toString(),
  ).add(
    newRewards
      .mul(WAD)
      .div(new Decimal(farmState.totalActiveStakeScaled.toString())),
  );

  return rewardPerToken;
}
