contract Rainbows is ERC20, Ownable, Pausable {

    InterfaceNoundles public Noundles;

    // The starting block.
    uint256 public startBlock;

    // The interval that the user is paid out.
    uint256 public interval = 86400;
    uint256 public rate     = 4 ether;

    address public ticketContract;

    // The rewards for the user.
    mapping(address => uint256) public rewards;

    // The last time they were paid out.
    mapping(address => uint256) public lastUpdate;

    // Only allow the contract to interact with it.
    modifier onlyFromNoundles() {
        require(msg.sender == address(Noundles));
        _;
    }

    constructor(address noundlesAddress) ERC20("NoundlesRainbows", "Rainbows") {

        // Set who the evofoxes address.
        Noundles = InterfaceNoundles(noundlesAddress);

        // Set the starting block.
        startBlock = block.timestamp;

        // Set to the owner for now.
        ticketContract = msg.sender;

        // Pause the system so no one can interact with it.
        _pause();
    }

    /*
        Admin Utility.
    */

    // Pause it.
    function pause() public onlyOwner { _pause(); }

    // Unpause it.
    function unpause() public onlyOwner { _unpause(); }

    // Set the start block.
    function setStartBlock(uint256 arg) public onlyOwner {
        if(arg == 0){
            startBlock = block.timestamp;
        }else{
            startBlock = arg;
        }
    }

    // Set the start block.
    function setIntervalAndRate(uint256 _interval, uint256 _rate) public onlyOwner {
        interval = _interval;
        rate = _rate;
    }


    // Set the address for the contract.
    function setNoundlesContractAddress(address _noundles) public onlyOwner {
        Noundles = InterfaceNoundles(_noundles);
    }

     // Set the address for the contract.
    function setTicketContractAddress(address _noundles) public onlyOwner {
        ticketContract = _noundles;
    }

    // Burn the tokens required to evolve.
    function burn(address user, uint256 amount) external {
        require(msg.sender == address(ticketContract), "Your address does not have permission to use burn");
        _burn(user, amount);
    }

    // Mint some tokens for uniswap.
    function adminCreate(address user, uint256 amount) public onlyOwner {
        _mint(user, amount);
    }


    /*
        User Utilities.
    */

    // Transfer the tokens (only accessable from the contract).
    function transferTokens(address _from, address _to) onlyFromNoundles whenNotPaused external {

        // Refactor this.
        if(_from != address(0)){
            rewards[_from]    += getPendingReward(_from);
            lastUpdate[_from]  = block.timestamp;
        }

        if(_to != address(0)){
            rewards[_to]    += getPendingReward(_to);
            lastUpdate[_to]  = block.timestamp;
        }
    }

    // Pay out the holder.
    function claimReward() external whenNotPaused {

        // Mint the user their tokens.
        _mint(msg.sender, rewards[msg.sender] + getPendingReward(msg.sender));

        // Reset the rewards for the user.
        rewards[msg.sender] = 0;
        lastUpdate[msg.sender] = block.timestamp;
    }

    // The rewards to the user.
    function getTotalClaimable(address user) external view returns(uint256) {
        return rewards[user] + getPendingReward(user);
    }

    // The rewards to the user.
    function getlastUpdate(address user) external view returns(uint256) {
        return lastUpdate[user];
    }

    // Get the total rewards.
    function getPendingReward(address user) internal view returns(uint256) {
        return Noundles.noundleBalance(user) * 
               rate *
               (block.timestamp - (lastUpdate[user] >= startBlock ? lastUpdate[user] : startBlock)) / 
               interval;
    }
}
function setNoundlesContractAddress(address _noundles) public onlyOwner {
    Noundles = InterfaceNoundles(_noundles);
}

// Set the address for the contract.