contract IDODistribution is Owned, Pausable {
    
    using SafeMath for uint;

    /**
     * @notice Authorised address able to call batchDeposit
     */
    address public authority;

    /**
     * @notice Address of ERC20 token
     */
    address public erc20Address;


    mapping(address => uint) balances;
    mapping(address => uint) counts;

    uint public totalSupply;

    constructor(
        address _owner,
        address _authority
    ) public Owned(_owner) {
        authority = _authority;
    }

    function balanceOf(address _address) public view returns (uint) {
        return balances[_address];
    }

    function depositNumberOf(address _address) public view returns (uint) {
        return counts[_address];
    }

    // ========== EXTERNAL SETTERS ==========

    function setTokenAddress(address _erc20Address) public onlyOwner {
        erc20Address = _erc20Address;
    }

    /**
     * @notice Set the address of the contract authorised to call distributeReward()
     * @param _authority Address of the authorised calling contract.
     */
    function setAuthority(address _authority) public onlyOwner {
        authority = _authority;
    }

    function batchDeposit(address[] destinations, uint[] amounts) public returns (bool) {
        require(msg.sender == authority, "Caller is not authorized");
        require(erc20Address != address(0), "erc20 token address is not set");
        require(destinations.length == amounts.length, "length of inputs not match");

        // we don't need check amount[i] > 0 or destinations != 0x0 because they cannot claim anyway
        uint amount = 0;
        for (uint i = 0; i < amounts.length; i++) {
            amount = amount.add(amounts[i]);
            balances[destinations[i]] =  balances[destinations[i]].add(amounts[i]);
            counts[destinations[i]] += 1;
        }

        totalSupply = totalSupply.add(amount);

        emit TokenDeposit(amount);
        return true;
    }

    function claim() public whenNotPaused returns (bool) {
        require(erc20Address != address(0), "erc20 token address is not set");
        require(balances[msg.sender] > 0, "account balance is zero");

        uint _amount = balances[msg.sender];
        require(
            IERC20(erc20Address).balanceOf(address(this)) >= _amount,
            "This contract does not have enough tokens to distribute"
        );

        balances[msg.sender] = 0;
        IERC20(erc20Address).transfer(msg.sender, _amount);
        totalSupply = totalSupply.sub(_amount);

        emit UserClaimed(msg.sender, _amount);
        return true;
    }

    /* ========== Events ========== */
    event TokenDeposit(uint _amount);
    event UserClaimed(address _address, uint _amount);
}
function setTokenAddress(address _erc20Address) public onlyOwner {
    erc20Address = _erc20Address;
}

// ========== EXTERNAL SETTERS ==========