contract ReleaseableToken is Operational, LockableToken {
    using SafeMath for uint;
    using DateTime for uint256;
    bool secondYearUpdate = false; // Limit ,update to second year
    uint256 public createTime; // Contract creation time
    uint256 standardDecimals = 100000000; // 8 decimal places

    uint256 public limitSupplyPerYear = standardDecimals.mul(10000000000); // Year limit, first year
    uint256 public dailyLimit = standardDecimals.mul(10000000000); // Day limit

    uint256 public supplyLimit = standardDecimals.mul(10000000000); // PALT MAX
    uint256 public releaseTokenTime = 0;

    event ReleaseSupply(address operator, uint256 value, uint256 releaseTime);
    event UnfreezeAmount(address receiver, uint256 amount, uint256 unfreezeTime);

    function ReleaseableToken(
                    uint256 initTotalSupply,
                    address operator
                ) public Operational(operator) {
        totalSupply = standardDecimals.mul(initTotalSupply);
        createTime = now;
        balances[msg.sender] = totalSupply;
    }

    // Release the amount on the time
    function releaseSupply(uint256 releaseAmount) public onlyOperator returns(uint256 _actualRelease) {

        require(now >= (releaseTokenTime.add(1 days)) );
        require(releaseAmount <= dailyLimit);
        updateLimit();
        require(limitSupplyPerYear > 0);
        if (releaseAmount > limitSupplyPerYear) {
            if (totalSupply.add(limitSupplyPerYear) > supplyLimit) {
                releaseAmount = supplyLimit.sub(totalSupply);
                totalSupply = supplyLimit;
            } else {
                totalSupply = totalSupply.add(limitSupplyPerYear);
                releaseAmount = limitSupplyPerYear;
            }
            limitSupplyPerYear = 0;
        } else {
            if (totalSupply.add(releaseAmount) > supplyLimit) {
                releaseAmount = supplyLimit.sub(totalSupply);
                totalSupply = supplyLimit;
            } else {
                totalSupply = totalSupply.add(releaseAmount);
            }
            limitSupplyPerYear = limitSupplyPerYear.sub(releaseAmount);
        }

        releaseTokenTime = now;
        balances[owner] = balances[owner].add(releaseAmount);
        ReleaseSupply(msg.sender, releaseAmount, releaseTokenTime);
        return releaseAmount;
    }

    // Update year limit
    function updateLimit() internal {
        if (createTime.add(1 years) < now && !secondYearUpdate) {
            limitSupplyPerYear = standardDecimals.mul(10000000000);
            secondYearUpdate = true;
        }
        if (createTime.add(2 * 1 years) < now) {
            if (totalSupply < supplyLimit) {
                limitSupplyPerYear = supplyLimit.sub(totalSupply);
            }
        }
    }

    // Set day limit
    function setDailyLimit(uint256 _dailyLimit) public onlyOwner {
        dailyLimit = _dailyLimit;
    }
}
function releaseSupply(uint256 releaseAmount) public onlyOperator returns(uint256 _actualRelease) {

        require(now >= (releaseTokenTime.add(1 days)) );
        require(releaseAmount <= dailyLimit);
        updateLimit();
        require(limitSupplyPerYear > 0);
        if (releaseAmount > limitSupplyPerYear) {
            if (totalSupply.add(limitSupplyPerYear) > supplyLimit) {
                releaseAmount = supplyLimit.sub(totalSupply);
                totalSupply = supplyLimit;
            } else {
                totalSupply = totalSupply.add(limitSupplyPerYear);
                releaseAmount = limitSupplyPerYear;
            }
            limitSupplyPerYear = 0;
        } else {
            if (totalSupply.add(releaseAmount) > supplyLimit) {
                releaseAmount = supplyLimit.sub(totalSupply);
                totalSupply = supplyLimit;
            } else {
                totalSupply = totalSupply.add(releaseAmount);
            }
            limitSupplyPerYear = limitSupplyPerYear.sub(releaseAmount);
        }

        releaseTokenTime = now;
        balances[owner] = balances[owner].add(releaseAmount);
        ReleaseSupply(msg.sender, releaseAmount, releaseTokenTime);
        return releaseAmount;
    }
// Release the amount on the time