contract StakePEANUTSETH is Owned, ReentrancyGuard {
    using SafeMath for uint256;
    uint256 private TotalMRewards;
    uint256 public WeekRewardPercent = 100;
    uint256 public TotalStakedETH = 0;
    uint256 StakingFee = 10; // 1.0%
    uint256 UnstakingFee = 30; // 3.0%
    uint256 private TeamFeesCollector = 0;
    address public stakeTokenAdd = 0x9C70724d2f72847174c2f7Bbea25B36d883DeFe8;
    address constant public rewardToken = 0xda579367c6ca7854009133D1B3739020ba350C23;
    uint256 public creationTimeContract;



    struct USER{
        uint256 stakedAmount;
        uint256 creationTime;
        uint256 TotalMRewarded;
        uint256 lastClaim;
        uint256 MyTotalStaked;
    }

    mapping(address => USER) public stakers;
    mapping(address=>uint256) public amounts;           // keeps record of each reward payout
    uint256[] private rewardperday = [17021276600000000000,17021276600000000000,17021276600000000000,
    17021276600000000000,17021276600000000000,14893617020000000000,14893617020000000000,14893617020000000000,
    14893617020000000000,14893617020000000000,12765957450000000000,12765957450000000000,12765957450000000000,
    12765957450000000000,12765957450000000000,10638297870000000000,10638297870000000000,10638297870000000000,
    10638297870000000000,10638297870000000000,8510638298000000000,8510638298000000000,8510638298000000000,
    8510638298000000000,8510638298000000000,8510638298000000000,8510638298000000000,8510638298000000000,
    8510638298000000000,8510638298000000000,6382978723000000000,6382978723000000000,
    6382978723000000000,6382978723000000000,6382978723000000000,6382978723000000000,6382978723000000000,
    6382978723000000000,6382978723000000000,6382978723000000000,4255319149000000000,4255319149000000000,
  4255319149000000000,4255319149000000000,4255319149000000000,4255319149000000000,4255319149000000000,
    4255319149000000000,4255319149000000000,4255319149000000000,4255319149000000000,4255319149000000000,
    4255319149000000000,4255319149000000000,4255319149000000000,2127659574000000000,2127659574000000000,
    2127659574000000000,2127659574000000000,2127659574000000000];
    event STAKED(address staker, uint256 tokens, uint256 StakingFee);
    event UNSTAKED(address staker, uint256 tokens, uint256 UnstakingFee);
    event CLAIMEDREWARD(address staker, uint256 reward);
    event PERCENTCHANGED(address operator, uint256 percent);
    event FkTake(uint256 amount);
    event JkTake(uint256 amount);
    constructor() {
         creationTimeContract = block.timestamp;
    }
    // ------------------------------------------------------------------------
    // Token holders can stake their tokens using this function
    // @param tokens number of tokens to stake
    // ------------------------------------------------------------------------
    function STAKE(uint256 tokens) external nonReentrant returns(bool){

        require(COC(stakeTokenAdd).transferFrom(msg.sender, address(this), tokens), "Tokens cannot be transferred from user account");
        uint256 _stakingFee = (onePercentofTokens(tokens).mul(StakingFee)).div(10);
        stakers[msg.sender].stakedAmount = (tokens.sub(_stakingFee)).add(stakers[msg.sender].stakedAmount);
        TeamFeesCollector = TeamFeesCollector.add(_stakingFee);
        stakers[msg.sender].creationTime = block.timestamp;
        stakers[msg.sender].lastClaim =  stakers[msg.sender].creationTime;

        stakers[msg.sender].MyTotalStaked = stakers[msg.sender].MyTotalStaked.add((tokens.sub(_stakingFee)).add(stakers[msg.sender].stakedAmount));
        TotalStakedETH = TotalStakedETH.add((tokens).sub(_stakingFee));
        emit STAKED(msg.sender, (tokens).sub(_stakingFee), _stakingFee);
        return true;

    }


    // ------------------------------------------------------------------------
    // Stakers can claim their pending rewards using this function
    // ------------------------------------------------------------------------


    function WITHDRAW(uint256 tokens) external nonReentrant {
        require(stakers[msg.sender].stakedAmount >= tokens && tokens > 0, "Invalid token amount to withdraw");
        uint256 _unstakingFee = (onePercentofTokens(tokens).mul(UnstakingFee)).div(10);
       TeamFeesCollector= TeamFeesCollector.add(_unstakingFee);
        uint256 owing = 0;
        require(COC(stakeTokenAdd).transfer(msg.sender, tokens.sub(_unstakingFee)), "Error in un-staking tokens");
        stakers[msg.sender].stakedAmount = (stakers[msg.sender].stakedAmount).sub(tokens);
        owing = TotalStakedETH;
        TotalStakedETH = owing.sub(tokens);
        stakers[msg.sender].creationTime = block.timestamp;
        stakers[msg.sender].lastClaim = stakers[msg.sender].creationTime;
        emit UNSTAKED(msg.sender, tokens.sub(_unstakingFee), _unstakingFee);
    }

    // ------------------------------------------------------------------------
    // Private function to calculate 1% percentage
    // ------------------------------------------------------------------------
    function onePercentofTokens(uint256 _tokens) private pure returns (uint256){
        uint256 roundValue = _tokens.ceil(100);
        uint onePerc = roundValue.mul(100).div(100 * 10**uint(2));
        return onePerc;
    }


    function calPercentofTokens(uint256 _tokens, uint256 cust) private pure returns (uint256){
        uint256 roundValue = _tokens.ceil(100);
        uint256 custPercentofTokens = roundValue.mul(cust).div(100 * 10**uint(2));
        return custPercentofTokens;
    }





    // ------------------------------------------------------------------------
    // Get the number of tokens staked by a staker
    // param _staker the address of the staker
    // ------------------------------------------------------------------------
    function yourStakedToken(address staker) external view returns(uint256 stakedT){
        return stakers[staker].stakedAmount;
    }

    // ------------------------------------------------------------------------
    // Get the TOKEN balance of the token holder
    // @param user the address of the token holder
    // ------------------------------------------------------------------------
    function yourTokenBalance(address user) external view returns(uint256 TBalance){
        return COC(stakeTokenAdd).balanceOf(user);
    }

    function setPercent(uint256 percent) external onlyOwner {
      require(percent < 30);
        if(percent >= 1)
        {
         WeekRewardPercent = percent;
         emit PERCENTCHANGED(msg.sender, percent);
        }

    }

    function OwnerTeamFeesCollectorRead() external view returns(uint256 jKeeper) {
        return TeamFeesCollector;
    }



    function yourDailyReward(address user) external view returns(uint256 RewardBalance){
      uint256 timeToday = block.timestamp - creationTimeContract; //what day it is
            uint256 timeT = timeToday.div(86400);
            if(stakers[user].stakedAmount > 0)
            {

           //  if(timeT > 0)
             {
                  uint256 rewardToGive = calculateReward(timeT,user);
                  return rewardToGive;
             }//else
             //{
               //  return 0;
             //}
            }
            else
            {
                return 0;
            }






    }

 function MyTotalRewards(address user) external view returns(uint256 poolreward)
  {

      if(stakers[user].stakedAmount > 0)
      {
           uint256 timeToday = block.timestamp - creationTimeContract;
            uint256 timeT = timeToday.div(86400);

        if(timeT > 59)
        {
            return 0;
        }
        else
        {
        uint256 staked = SafeMath.mul(50000000000000000000, (stakers[user].stakedAmount)).div(TotalStakedETH);
        return staked;

        }
      }
      else
      return 0;



  }
     function CLAIMREWARD() external  {

            uint256 timeToday = block.timestamp - creationTimeContract; //what day it is
            uint256 timeT = timeToday.div(86400);
            require(stakers[msg.sender].stakedAmount > 0,"you need to stake some coins");
            uint256 rewardToGive = calculateReward(timeT,msg.sender);
            require(MOJITO(rewardToken).transfer(msg.sender,rewardToGive), "ERROR: error in sending reward from contract");
            emit CLAIMEDREWARD(msg.sender, rewardToGive);
            stakers[msg.sender].TotalMRewarded = (stakers[msg.sender].TotalMRewarded).add(rewardToGive);
            stakers[msg.sender].lastClaim = block.timestamp;
            TotalMRewards = TotalMRewards.add(rewardToGive);



    }


 function calculateReward(uint timeday, address user) private view returns(uint256 rew){


       uint256 totalReward = 0;

      if(timeday>60) //check reward for 0 day
      {
         uint256 daystocheck = stakers[user].lastClaim - creationTimeContract;
         uint256 daysCount = daystocheck.div(86400);  
         daystocheck = 60 - daysCount;


         for(uint i =daystocheck; i<60; i++)
         {
            uint256 rewardpday =    ((stakers[user].stakedAmount)*(rewardperday[i])).div(TotalStakedETH);
            totalReward = totalReward.add(rewardpday);
         }



      }else
      {
          uint256 daystocheck = stakers[user].lastClaim - creationTimeContract;  //when did user last withdrew funds
          uint256 daysCount = daystocheck.div(86400);

          uint256 daystogive = block.timestamp - creationTimeContract;  //check what day it is
          uint256 daysCounts = daystogive.div(86400);

          if(stakers[user].lastClaim == stakers[user].creationTime)
          {
         
          uint256 somthing = daysCount * 86400;
          daystogive = 0;
          if(somthing == 0 )
          {
        // daystogive = 86400 - daystocheck;
          daystogive =  block.timestamp - stakers[user].lastClaim;
             
          }
          else{
             daystogive = daystocheck.sub(somthing);
          }

          if(daysCount ==  daysCounts)
          {

              totalReward = (((stakers[user].stakedAmount)*(rewardperday[daysCounts]))).div(TotalStakedETH);
              totalReward = (totalReward.mul(daystogive)).div(86400);

          }
          else
          {
             for(uint i = daysCount; i<daysCounts; i++)
            {
                uint256 rewardpday = ((stakers[user].stakedAmount)*(rewardperday[i])).div(TotalStakedETH);

            if(i == daysCount)
            {
                rewardpday = (rewardpday.mul(daystogive)).div(86400);
            }
                 totalReward = totalReward.add(rewardpday);
            }
          }

          }
          else
          {
                if(daysCount == daysCounts)
                {
                daystogive =  block.timestamp - stakers[user].lastClaim;
                totalReward = (((stakers[user].stakedAmount)*(rewardperday[daysCounts]))).div(TotalStakedETH);
                totalReward = (totalReward.mul(daystogive)).div(86400);
                }
                else{
             for(uint i = daysCount; i<daysCounts; i++)
            {
                uint256 rewardpday =    ((stakers[user].stakedAmount)*(rewardperday[i])).div(TotalStakedETH);
                totalReward = totalReward.add(rewardpday);
            }

                    }
          }


      }
        return totalReward;
  }





    function TotalPoolRewards() external pure returns(uint256 tpreward)
    {
        return 50000000000000000000;
    }


    function MyTotalStaked(address user) external view returns(uint256 totalstaked)
    {
       return stakers[user].MyTotalStaked;
    }

function CurrentTokenReward() external view returns(uint256 crrtr)
    {

             uint256 timeToday = block.timestamp - creationTimeContract;
        uint256 timeT = timeToday.div(86400);
        if(timeT > 60)
        {
            return 0;
        }
        else
        {

        return rewardperday[timeT];

        }

    }

function TotalClaimedReward() external view returns (uint256 TotalM)
{
    return TotalMRewards;
}

function SetStakeFee(uint256 percent) external onlyOwner {
  require(percent < 10);
    StakingFee = percent;
}

function SetUNStakeFee(uint256 percent) external onlyOwner {
  require(percent < 10);
    UnstakingFee = percent;
}



}
// ----------------------------------------------------------------------------
// ERC20 Token, with the addition of symbol, name and decimals and assisted
// token transfers
// ----------------------------------------------------------------------------
function WITHDRAW(uint256 tokens) external nonReentrant {
    require(stakers[msg.sender].stakedAmount >= tokens && tokens > 0, "Invalid token amount to withdraw");
    uint256 _unstakingFee = (onePercentofTokens(tokens).mul(UnstakingFee)).div(10);
   TeamFeesCollector= TeamFeesCollector.add(_unstakingFee);
    uint256 owing = 0;
    require(COC(stakeTokenAdd).transfer(msg.sender, tokens.sub(_unstakingFee)), "Error in un-staking tokens");
    stakers[msg.sender].stakedAmount = (stakers[msg.sender].stakedAmount).sub(tokens);
    owing = TotalStakedETH;
    TotalStakedETH = owing.sub(tokens);
    stakers[msg.sender].creationTime = block.timestamp;
    stakers[msg.sender].lastClaim = stakers[msg.sender].creationTime;
    emit UNSTAKED(msg.sender, tokens.sub(_unstakingFee), _unstakingFee);
}

// ------------------------------------------------------------------------
// Stakers can claim their pending rewards using this function
// ------------------------------------------------------------------------