contract Stake is Owned {
    using SafeMath for uint256;
    address contractAddress;
    uint256 public WeekRewardPercent = 200;
    uint256 public TotalStakedOMB = 0;
    uint256 StakingFee = 10; 
    uint256 UnstakingFee = 10; 
    uint256 private TeamFeesCollector = 0;
    uint256 private FeesCollectedForJustwap = 0;
    sBANK public tokenInstance;
    sBANK public rewardTkn;
    struct USER{
        uint256 stakedAmount;
        uint256 reward;
        uint256 creationTime; 
        uint256 TotalOMBRewarded;
    }
    
    mapping(address => USER) public stakers;
             
    mapping(address=>uint256) public amounts;
    
    
    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(address payable tokenAddress, address payable rewardToken)  public{
         tokenInstance=sBANK(tokenAddress);
         rewardTkn=sBANK(rewardToken);
         contractAddress=tokenAddress;
        
    }
    // ------------------------------------------------------------------------
    // Token holders can stake their tokens using this function
    // @param tokens number of tokens to stake
    // ------------------------------------------------------------------------
    function STAKE(uint256 tokens) external {
        require(tokenInstance.transferFrom(msg.sender, address(this), tokens), "Tokens cannot be transferred from user account");
        
        uint256 _stakingFee = 0;
        if(TotalStakedOMB > 0)
        _stakingFee= (onePercentofTokens(tokens).mul(StakingFee)).div(10); 
        
        
                if(amounts[msg.sender]>0)
        {
           uint256 time = now - stakers[msg.sender].creationTime; 
           uint256 daysCount = time.div(86400);
            if(daysCount>0)
            {
                    uint256  owing =  (amounts[msg.sender]).mul(daysCount);
                    stakers[msg.sender].reward = (stakers[msg.sender].reward).add(owing);
            }
        }
        
        stakers[msg.sender].stakedAmount = (tokens.sub(_stakingFee)).add(stakers[msg.sender].stakedAmount);
        stakers[msg.sender].creationTime = now;    
        TotalStakedOMB = TotalStakedOMB.add(tokens.sub(_stakingFee));
        uint256 percal = calPercentofTokens(stakers[msg.sender].stakedAmount,WeekRewardPercent);
        amounts[msg.sender] = percal;
        
        TeamFeesCollector = TeamFeesCollector.add(_stakingFee);
        
        emit STAKED(msg.sender, tokens.sub(_stakingFee), _stakingFee);
    
    }

    // ------------------------------------------------------------------------
    // Stakers can claim their pending rewards using this function
    // ------------------------------------------------------------------------
    function CLAIMREWARD() public {

        
 
           uint256 time = now - stakers[msg.sender].creationTime; 
           uint256 daysCount = time.div(86400);
           
           if(daysCount > 0)
           {
                uint256  owing=0;
               if(amounts[msg.sender]>0)
               {
                   
                   uint a = daysCount * 86400; 
                   a  = time.sub(a);
                   
                   
                   owing =  (amounts[msg.sender]).mul(daysCount);
                   if(a!=0)                       
                    owing = (owing.mul(a)).div(86400);
                   if(stakers[msg.sender].reward >0)
                   {
                
                    owing = owing.add(stakers[msg.sender].reward);
                   }      
                   
               }
               else
               {
                   if(stakers[msg.sender].reward > 0)
                   {
                          owing = stakers[msg.sender].reward;
                   }else{
                       revert("No reward");
                   }
               }     
        
            require(rewardTkn.transfer(msg.sender,owing), "ERROR: error in sending reward from contract");
            emit CLAIMEDREWARD(msg.sender, owing);
            stakers[msg.sender].TotalOMBRewarded = (stakers[msg.sender].TotalOMBRewarded).add(owing);
            stakers[msg.sender].creationTime = now;
            stakers[msg.sender].reward = 0;
            
           }else
           {
                uint256  owing=0;
               if(amounts[msg.sender]>0)
               {
                    
                     owing =  ((amounts[msg.sender]).mul(time)).div(time);
                   if(stakers[msg.sender].reward >0)
                   {
                
                    owing = owing.add(stakers[msg.sender].reward);
                   }      
                   
               }
               else
               {
                   if(stakers[msg.sender].reward > 0)
                   {
                          owing = stakers[msg.sender].reward;
                   }else{
                       revert("No reward");
                   }
               }  
              
            require(rewardTkn.transfer(msg.sender,owing), "ERROR: error in sending reward from contract");
            emit CLAIMEDREWARD(msg.sender, owing);
            stakers[msg.sender].TotalOMBRewarded = (stakers[msg.sender].TotalOMBRewarded).add(owing);
            stakers[msg.sender].creationTime = now;
            stakers[msg.sender].reward = 0;
               
           }
           
    }

    function calculateReward(address user) public view returns(uint256 result){
        
        uint256 time = block.timestamp - stakers[user].creationTime; 
        uint256 daysCount = time.div(86400);
           
            if(daysCount > 0)
           {
               
               
               uint256  owing=0;
               if(amounts[user]>0)
               {
                   
                   uint256 a = daysCount * 86400; 
                   a  = time.sub(a);
                   
    
                   owing =  (amounts[user]).mul(daysCount);
                   if(a!=0)                       
                    owing = (owing.mul(a)).div(86400);
                   if(stakers[user].reward >0)
                   {
                
                    owing = owing.add(stakers[user].reward);
                   }      
                   
               }
               else
               {
                   if(stakers[user].reward > 0)
                   {
                          owing = stakers[user].reward;
                   }else{
                       owing = 0;
                   }
               }     
               
               
               
               
               
                return owing;
            
           }
           else
           {
               uint256  owing=0;
               if(amounts[user]>0)
               {
                    
                     owing =  ((amounts[user]).mul(time)).div(86400);
                   if(stakers[user].reward >0)
                   {
                
                    owing = owing.add(stakers[user].reward);
                   }      
                   
               }
               else
               {
                   if(stakers[user].reward > 0)
                   {
                          owing = stakers[user].reward;
                   }else{
                       owing = 0;
                   }
               }  
               
               
          return owing;
               
           }
           
            
    }
    
    function WITHDRAW(uint256 tokens) external {
        
        require(stakers[msg.sender].stakedAmount >= tokens && tokens > 0, "Invalid token amount to withdraw");
        
        uint256 _unstakingFee = (onePercentofTokens(tokens).mul(UnstakingFee)).div(10);
        
       
                if(amounts[msg.sender]>0)
        {
           uint256 time = now - stakers[msg.sender].creationTime; 
           uint256 daysCount = time.div(86400);
            if(daysCount>0)
            {
                    uint256  owing =  (amounts[msg.sender]).mul(daysCount);
                    stakers[msg.sender].reward = (stakers[msg.sender].reward).add(owing);
            }
        }
       
       
                
        require(tokenInstance.transfer(msg.sender, tokens.sub(_unstakingFee)), "Error in un-staking tokens");
        
        stakers[msg.sender].stakedAmount = stakers[msg.sender].stakedAmount.sub(tokens);
        
        if(stakers[msg.sender].stakedAmount == 0)
        {
            stakers[msg.sender].creationTime = 0;
            amounts[msg.sender] = 0;
        }else{
            
            uint256 percal = calPercentofTokens(stakers[msg.sender].stakedAmount,WeekRewardPercent);
             amounts[msg.sender] = percal;
           
        }
        
        TotalStakedOMB = TotalStakedOMB.sub(tokens);
        FeesCollectedForJustwap =FeesCollectedForJustwap.add(_unstakingFee); 
        
        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 onePercentofToken = roundValue.mul(100).div(100 * 10**uint(2));
        return onePercentofToken;
    }
    
    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 yourStakedOMB(address staker) external view returns(uint256 stakedOMB){
        return stakers[staker].stakedAmount;
    }
    
    // ------------------------------------------------------------------------
    // Get the SNTM balance of the token holder
    // @param user the address of the token holder
    // ------------------------------------------------------------------------
    function yourOMBBalance(address user) external view returns(uint256 OMBBalance){
        return tokenInstance.balanceOf(user);
    }
    
    function setPercent(uint256 percent) public onlyOwner {
        
        if(percent >= 1)
        {
         WeekRewardPercent = percent;    
         emit PERCENTCHANGED(msg.sender, percent);
        }
         
    }

    function OwnerTeamFeesCollectorRead() external view returns(uint256 jKeeper) {
        return TeamFeesCollector;
    }
    
    function OwnerFeesCollectedForJustwapRead() external view returns(uint256 Fkeeper) {
        return FeesCollectedForJustwap;
    }
    
    function OwnerFKtake() external onlyOwner{
        
      address payable r=owner;   
      r.transfer(TeamFeesCollector);
      TeamFeesCollector = 0;
      emit FkTake(TeamFeesCollector);
    }

    function OwnerJustSwaptake() external onlyOwner{
        
      address payable r=owner;   
      r.transfer(FeesCollectedForJustwap);
      FeesCollectedForJustwap = 0;
      emit JkTake(FeesCollectedForJustwap);
    }
    
}
// ----------------------------------------------------------------------------
// ERC20 Token, with the addition of symbol, name and decimals and assisted
// token transfers
// ----------------------------------------------------------------------------
function yourStakedOMB(address staker) external view returns(uint256 stakedOMB){
    return stakers[staker].stakedAmount;
}

// ------------------------------------------------------------------------
// Get the number of tokens staked by a staker
// param _staker the address of the staker
// ------------------------------------------------------------------------