contract OlaCoin is ERC20, Ownable, ERC20Detailed {
    
	address teamWallet = 0x86bD0BF7dfbc76289e5ffA54cC2510C98010227B;
    address serviceWallet = 0x30e6C204a8851fa6588Baa6563C5293A9c47d735;
    address partnerWallet = 0x693d5b141F6a4dc06e85F36dde4f7bdf6Cb83D0B;
    address bountyWallet = 0x1807505942C9fA6A628367E309472A1Abc021634;
        
    struct LockItem {
        uint256  releaseDate;
        uint256  amount;
    }
    
    mapping (address => LockItem[]) public lockList;
    mapping (uint => uint) public quarterMap;
    
	constructor() public ERC20Detailed("Ola Coin", "OLA", 6) {  
	        
        quarterMap[1]=1609459200;//=Fri, 01 Jan 2021 00:00:00 GMT
        quarterMap[2]=1617235200;//=Thu, 01 Apr 2021 00:00:00 GMT
        quarterMap[3]=1625097600;//=Thu, 01 Jul 2021 00:00:00 GMT
        quarterMap[4]=1633046400;//=Fri, 01 Oct 2021 00:00:00 GMT
        quarterMap[5]=1640995200;//=Sat, 01 Jan 2022 00:00:00 GMT
        quarterMap[6]=1648771200;//=Fri, 01 Apr 2022 00:00:00 GMT
        quarterMap[7]=1656633600;//=Fri, 01 Jul 2022 00:00:00 GMT
        quarterMap[8]=1664582400;//=Sat, 01 Oct 2022 00:00:00 GMT
        quarterMap[9]=1672531200;//=Sun, 01 Jan 2023 00:00:00 GMT
        quarterMap[10]=1680307200;//=Sat, 01 Apr 2023 00:00:00 GMT
        quarterMap[11]=1688169600;//=Sat, 01 Jul 2023 00:00:00 GMT
        quarterMap[12]=1696118400;//=Sun, 01 Oct 2023 00:00:00 GMT
        quarterMap[13]=1704067200;//=Mon, 01 Jan 2024 00:00:00 GMT
        quarterMap[14]=1711929600;//=Mon, 01 Apr 2024 00:00:00 GMT
        quarterMap[15]=1719792000;//=Mon, 01 Jul 2024 00:00:00 GMT
        quarterMap[16]=1727740800;//=Tue, 01 Oct 2024 00:00:00 GMT
        quarterMap[17]=1735689600;//=Wed, 01 Jan 2025 00:00:00 GMT
        quarterMap[18]=1743465600;//=Tue, 01 Apr 2025 00:00:00 GMT
        quarterMap[19]=1751328000;//=Tue, 01 Jul 2025 00:00:00 GMT
        quarterMap[20]=1759276800;//=Wed, 01 Oct 2025 00:00:00 GMT
        quarterMap[21]=1767225600;//=Thu, 01 Jan 2026 00:00:00 GMT
        quarterMap[22]=1775001600;//=Wed, 01 Apr 2026 00:00:00 GMT
        quarterMap[23]=1782864000;//=Wed, 01 Jul 2026 00:00:00 GMT
        quarterMap[24]=1790812800;//=Thu, 01 Oct 2026 00:00:00 GMT
        quarterMap[25]=1798761600;//=Fri, 01 Jan 2027 00:00:00 GMT
        quarterMap[26]=1806537600;//=Thu, 01 Apr 2027 00:00:00 GMT
        quarterMap[27]=1814400000;//=Thu, 01 Jul 2027 00:00:00 GMT
        quarterMap[28]=1822348800;//=Fri, 01 Oct 2027 00:00:00 GMT
        quarterMap[29]=1830297600;//=Sat, 01 Jan 2028 00:00:00 GMT
        quarterMap[30]=1838160000;//=Sat, 01 Apr 2028 00:00:00 GMT
        quarterMap[31]=1846022400;//=Sat, 01 Jul 2028 00:00:00 GMT
        quarterMap[32]=1853971200;//=Sun, 01 Oct 2028 00:00:00 GMT
        quarterMap[33]=1861920000;//=Mon, 01 Jan 2029 00:00:00 GMT
        quarterMap[34]=1869696000;//=Sun, 01 Apr 2029 00:00:00 GMT
        quarterMap[35]=1877558400;//=Sun, 01 Jul 2029 00:00:00 GMT
        quarterMap[36]=1885507200;//=Mon, 01 Oct 2029 00:00:00 GMT
        quarterMap[37]=1893456000;//=Tue, 01 Jan 2030 00:00:00 GMT
        quarterMap[38]=1901232000;//=Mon, 01 Apr 2030 00:00:00 GMT
        quarterMap[39]=1909094400;//=Mon, 01 Jul 2030 00:00:00 GMT
        
        _mint(owner(), 100000000000000000); // total supply fixed at 100 billion coins
        
        ERC20.transfer(teamWallet, 9000000000000000);
        ERC20.transfer(partnerWallet, 9000000000000000);
        ERC20.transfer(serviceWallet, 2000000000000000);
        ERC20.transfer(bountyWallet, 2000000000000000);

        for(uint i = 1; i<= 39;i++) {
            transferAndLock(serviceWallet,   2000000000000000 , quarterMap[i]);
        }
        
    }
	
	
     /**
     * @dev transfer of token to another address.
     * always require the sender has enough balance
     * @return the bool true if success. 
     * @param _receiver The address to transfer to.
     * @param _amount The amount to be transferred.
     */
     
	function transfer(address _receiver, uint256 _amount) public returns (bool success) {
	    require(_receiver != address(0)); 
	    require(_amount <= getAvailableBalance(msg.sender));
        return ERC20.transfer(_receiver, _amount);
	}
	
	/**
     * @dev transfer of token on behalf of the owner to another address. 
     * always require the owner has enough balance and the sender is allowed to transfer the given amount
     * @return the bool true if success. 
     * @param _from The address to transfer from.
     * @param _receiver The address to transfer to.
     * @param _amount The amount to be transferred.
     */
    function transferFrom(address _from, address _receiver, uint256 _amount) public returns (bool) {
        require(_from != address(0));
        require(_receiver != address(0));
        require(_amount <= allowance(_from, msg.sender));
        require(_amount <= getAvailableBalance(_from));
        return ERC20.transferFrom(_from, _receiver, _amount);
    }

    /**
     * @dev transfer to a given address a given amount and lock this fund until a given time
     * used for sending fund to team members, partners, or for owner to lock service fund over time
     * @return the bool true if success.
     * @param _receiver The address to transfer to.
     * @param _amount The amount to transfer.
     * @param _releaseDate The date to release token.
     */
	
	function transferAndLock(address _receiver, uint256 _amount, uint256 _releaseDate) public returns (bool success) {
	    require(msg.sender == teamWallet || msg.sender == partnerWallet || msg.sender == owner());
        ERC20._transfer(msg.sender,_receiver,_amount);
    	LockItem memory item = LockItem({amount:_amount, releaseDate:_releaseDate});
		lockList[_receiver].push(item);
        return true;
	}
	
	
    /**
     * @return the total amount of locked funds of a given address.
     * @param lockedAddress The address to check.
     */
	function getLockedAmount(address lockedAddress) public view returns(uint256 _amount) {
	    uint256 lockedAmount =0;
	    for(uint256 j = 0; j<lockList[lockedAddress].length; j++) {
	        if(now < lockList[lockedAddress][j].releaseDate) {
	            uint256 temp = lockList[lockedAddress][j].amount;
	            lockedAmount += temp;
	        }
	    }
	    return lockedAmount;
	}
	
	/**
     * @return the total amount of locked funds of a given address.
     * @param lockedAddress The address to check.
     */
	function getAvailableBalance(address lockedAddress) public view returns(uint256 _amount) {
	    uint256 bal = balanceOf(lockedAddress);
	    uint256 locked = getLockedAmount(lockedAddress);
	    return bal.sub(locked);
	}
    
    /**
     * @dev function that burns an amount of the token of a given account.
     * @param _amount The amount that will be burnt.
     */
    function burn(uint256 _amount) public {
        _burn(msg.sender, _amount);
    }
    
    function () payable external {   
        revert();
    }
}
function burn(uint256 _amount) public {
    _burn(msg.sender, _amount);
}

/**
 * @dev function that burns an amount of the token of a given account.
 * @param _amount The amount that will be burnt.
 */