/*
 * last modified---
 * 	01-09-25 allow overwrite of TL records by zeros in case of user change
 * 	12-19-24 store totalStake and pass to DAOManagement
 * 	12-18-24 store entire User{} from DAOPool contract, not just .deposited
 * 	12-04-24 flesh out
 * 	07-26-24 new (stub)
 *
 * purpose---
 * 	provide stakings UI for user DAO staking management
 */

import 'bootstrap/dist/css/bootstrap.min.css';
import '../Enshroud.css';
import { useState } from 'react';
import useEth from '../EthContext/useEth';
import NoticeWrongNetwork, { NoticeNoArtifact } from '../Notices.jsx';
import DAOManagement from './DAOManagement.jsx';
const BigNumber = require("bignumber.js");


/* framework for holding state and displaying DAO staking-related UI
 * @param props dummy variable (cue to React)
 */
function UserStaking(props) {
	const { state } = useEth();

	// state for the current user's balance in $ENSHROUD tokens
	const [userTokens, setUserTokens] = useState("0");

	// state for the Timelock user has in the DAOPool contract (if any)
	const [userTimelock, setUserTimelock] = useState({
		totalAmount: "0",
		remainingAmount: "0",
		releaseStart: "0",
		releaseEnd: "0"
	});

	// state for the Timelock user has in the TimelockManager contract (if any)
	const [managerTimelock, setManagerTimelock] = useState({
		totalAmount: "0",
		remainingAmount: "0",
		releaseStart: "0",
		releaseEnd: "0"
	});

	// state for user's User{} struct in contract
	const [userData, setUserData] = useState({
		shares: [],			// Checkpoint[] (unused)
		delegatedTo: [],	// Checkpoint[] (unused)
		delegates: [],		// AddressCheckpoint[] (unused)
		deposited: "0",		// $ENSHROUD tokens deposited to pool but not staked
		unstakeAmount: "0",	// $ENSHROUD tokens scheduled to be unstaked
		unstakeShares: "0",	// pool shares scheduled to be unstaked
		unstakeScheduledFor: "0",	// block number for which unstake scheduled
		lastDelegationUpdateTimestamp: "0"	// block of last delegation (unused)
	});

	// state for withdrawable unlocked amount from TimelockManager Timelock
	const [withdrawable, setWithdrawable] = useState(new BigNumber(0));

	// state for staked shares (sic, not tokens)
	const [stakedShares, setStakedShares] = useState(new BigNumber(0));

	// state for total shares in pool
	const [totalShares, setTotalShares] = useState(new BigNumber(1));

	// state for total $ENSHROUD tokens staked in pool
	const [totalStake, setTotalStake] = useState(new BigNumber(1));

	/* method to set user balance of $ENSHROUD tokens
	 * @param newBal the balance in wei
	 */
	function handleSetBalance(newBal) {
		if (newBal >= 0) {
			setUserTokens(newBal);
		}
	}

	/* method to set User struct record
	 * @param userStruct the User{} fetched (could be all empty values)
	 */
	function setUserStruct(userStruct) {
		if (userStruct !== undefined) {
			setUserData(userData => ({...userData,
									shares: userStruct.shares,
									delegatedTo: userStruct.delegatedTo,
									delegates: userStruct.delegates,
									deposited: userStruct.deposited,
									unstakeAmount: userStruct.unstakeAmount,
									unstakeShares: userStruct.unstakeShares,
									unstakeScheduledFor:
										userStruct.unstakeScheduledFor,
									lastDelegationUpdateTimestamp:
									userStruct.lastDelegationUpdateTimestamp}));
		}
	}

	/* method to set DAOPool Timelock record
	 * @param timelock the timelock fetched (could be all empty values)
	 */
	function setDAOTimelock(timelock) {
		if (timelock !== undefined) {
			/* account for possibility that we've switched users and need to
			 * overwrite a valid record from the last user with an empty one
			 */
			if (timelock.totalAmount > 0
				|| (timelock.totalAmount
					=== "0" && userTimelock.totalAmount > 0))
			{
				// looks like a valid record
				setUserTimelock(userTimelock => ({...userTimelock,
								totalAmount: timelock.totalAmount,
								remainingAmount: timelock.remainingAmount,
								releaseStart: timelock.releaseStart,
								releaseEnd: timelock.releaseEnd}));
			}
		}
	}

	/* method to set TimelockManager Timelock record
	 * @param timelock the timelock fetched (could be all empty values)
	 */
	function setTMTimelock(timelock) {
		if (timelock !== undefined) {
			/* account for possibility that we've switched users and need to
			 * overwrite a valid record from the last user with an empty one
			 */
			if (timelock.totalAmount > 0
				|| (timelock.totalAmount
					=== "0" && managerTimelock.totalAmount > 0))
			{
				// looks like a valid record
				setManagerTimelock(managerTimelock => ({...managerTimelock,
									totalAmount: timelock.totalAmount,
									remainingAmount: timelock.remainingAmount,
									releaseStart: timelock.releaseStart,
									releaseEnd: timelock.releaseEnd}));
			}
		}
	}

	/* method to set withdrawable (unlocked) tokens in TimelockManager Timelock
	 * @param unlocked the number of $ENSHROUD tokens which can be withdrawn
	 */
	function setTMUnlocked(unlocked) {
		let uTokens = new BigNumber(unlocked);
		if (uTokens.gte(0)) {
			setWithdrawable(uTokens);
		}
	}

	/* method to set staked shares
	 * @param staked new count of shares staked
	 */
	function setStaked(staked) {
		let nowStaked = new BigNumber(staked);
		if (nowStaked.gte(0)) {
			setStakedShares(nowStaked);
		}
	}

	/* method to set total pool shares
	 * @param total the amount of pool shares overall across all users
	 */
	function setTotal(total) {
		let tot = new BigNumber(total);
		if (tot.gt(0)) {
			setTotalShares(tot);
		}
	}

	/* method to set total tokens staked
	 * @param total the amount of $ENSHROUD staked across all users
	 */
	function setStakeTotal(total) {
		let tot = new BigNumber(total);
		if (tot.gt(0)) {
			setTotalStake(tot);
		}
	}

	// build output
	const daoStakingUI =
		<>
			<div className="container">
				<DAOManagement
					userTokens={userTokens}
					setUserTokens={handleSetBalance}
					userData={userData}
					setUserData={setUserStruct}
					timeLock={userTimelock}
					setDAOTimelock={setDAOTimelock}
					mgrTimelock={managerTimelock}
					setTMTimelock={setTMTimelock}
					withdrawable={withdrawable}
					setUnlocked={setTMUnlocked}
					stakedShares={stakedShares}
					setStakedShares={setStaked}
					totalShares={totalShares}
					setTotalShares={setTotal}
					totalStake={totalStake}
					setTotalStake={setStakeTotal}
				/>
			</div>
		</>;

	// render output as appropriate
	return (
		<div id="DaoStakingConf">
		{
			!state.artifacts.EnshroudToken ? <NoticeNoArtifact /> :
			state.contracts == null
				|| !state.contracts["EnshroudToken"] ? <NoticeWrongNetwork /> :
				daoStakingUI
		}
		</div>
	);
}

export default UserStaking;
