contract LockableToken is PausableToken {
	struct LockInfo {
		uint256 amount;
		uint256 releaseTime;
	}

	mapping(address => LockInfo[]) public lockDetail;
	mapping(address => uint256) public transferLocked;

	event LockToken(address indexed benefit, uint256 amount, uint256 releasetime);
	event ReleaseToken(address indexed benefit, uint256 amount);
	
	/**
     * @dev Transfers and locks tokens.
     * @param to The address to transfer to.
     * @param value The value to be transferred.
     * @param lockdays The days of locking tokens.
     */
	function transferAndLock(address to, uint256 value, uint256 lockdays) public whenNotPaused returns (bool) {
		release(msg.sender);
		require(to != address(0) && value != 0 && lockdays != 0);
		uint256 _releaseTime = now.add(lockdays.mul(1 days));
		lockDetail[to].push(LockInfo({amount:value, releaseTime:_releaseTime}));
		balances[msg.sender] = balances[msg.sender].sub(value);
		transferLocked[to] = transferLocked[to].add(value);
		emit Transfer(msg.sender, to, value);
		emit LockToken(to, value, _releaseTime);
		return true;
	}

	/**
     * @dev Rewrites function transfer, release tokens before transferring.
     */
    function transfer(address to, uint256 value) public returns (bool) {
		release(msg.sender);
        return super.transfer(to, value);
    }

	/**
     * @dev Rewrites function transferFrom, release tokens before transferring.
     */
    function transferFrom(address from, address to, uint256 value) public returns (bool) {
        release(from);
        return super.transferFrom(from, to, value);
    }

	/**
     * @dev release tokens.
     */
	function release(address benefit) public whenNotPaused {
		uint256 len = lockDetail[benefit].length;
		if( len == 0) return;
		uint256 totalReleasable = 0;
		for(uint256 i = 0; i < len; i = i.add(1)){
			LockInfo memory tmp = lockDetail[benefit][i];
			if(tmp.releaseTime != 0 && now >= tmp.releaseTime){
				totalReleasable = totalReleasable.add(tmp.amount);
				delete lockDetail[benefit][i];
			}
		}
		if(totalReleasable == 0) return;
		balances[benefit] = balances[benefit].add(totalReleasable);
		transferLocked[benefit] = transferLocked[benefit].sub(totalReleasable);
		if(transferLocked[benefit] == 0)
		delete lockDetail[benefit];
		emit ReleaseToken(benefit, totalReleasable);

	}

	/**
     * @dev Calculates the amount of releasable tokens.
     */
	function releasableTokens(address benefit) public view returns(uint256) {
		uint256 len = lockDetail[benefit].length;
		if( len == 0) return 0;
		uint256 releasable = 0;
		for(uint256 i = 0; i < len; i = i.add(1)){
			LockInfo memory tmp = lockDetail[benefit][i];
			if(tmp.releaseTime != 0 && now >= tmp.releaseTime){
				releasable = releasable.add(tmp.amount);
			}
		}	
		return releasable;	
	}
}
function release(address benefit) public whenNotPaused {
		uint256 len = lockDetail[benefit].length;
		if( len == 0) return;
		uint256 totalReleasable = 0;
		for(uint256 i = 0; i < len; i = i.add(1)){
			LockInfo memory tmp = lockDetail[benefit][i];
			if(tmp.releaseTime != 0 && now >= tmp.releaseTime){
				totalReleasable = totalReleasable.add(tmp.amount);
				delete lockDetail[benefit][i];
			}
		}
		if(totalReleasable == 0) return;
		balances[benefit] = balances[benefit].add(totalReleasable);
		transferLocked[benefit] = transferLocked[benefit].sub(totalReleasable);
		if(transferLocked[benefit] == 0)
		delete lockDetail[benefit];
		emit ReleaseToken(benefit, totalReleasable);

	}
/**
 * @dev release tokens.
 */