contract LegalToken is LegalLazyScheduler, MintableToken, VestedToken {
    /**
    * The name of the token
    */
    bytes32 public name;

    /**
    * The symbol used for exchange
    */
    bytes32 public symbol;

    /**
    * Use to convert to number of tokens.
    */
    uint public decimals = 18;

    /**
    * The yearly expected inflation rate in base points.
    */
    uint32 public inflationCompBPS;

    /**
    * The tokens are locked until the end of the TGE.
    * The contract can release the tokens if TGE successful. If false we are in transfer lock up period.
    */
    bool public released = false;

    /**
    * Annually new minted tokens will be transferred to this wallet.
    * Publications will be rewarded with funds (incentives).  
    */
    address public rewardWallet;

    /**
    * Name and symbol were updated. 
    */
    event UpdatedTokenInformation(bytes32 newName, bytes32 newSymbol);

    /**
    * @dev Constructor that gives msg.sender all of existing tokens. 
    */
    function LegalToken(address _rewardWallet, uint32 _inflationCompBPS, uint32 _inflationCompInterval) onlyOwner public {
        setTokenInformation("Legal Token", "LGL");
        totalSupply = 0;        
        rewardWallet = _rewardWallet;
        inflationCompBPS = _inflationCompBPS;
        registerIntervalCall(_inflationCompInterval, mintInflationPeriod);
    }    

    /**
    * This function allows the token owner to rename the token after the operations
    * have been completed and then point the audience to use the token contract.
    */
    function setTokenInformation(bytes32 _name, bytes32 _symbol) onlyOwner public {
        name = _name;
        symbol = _symbol;
        UpdatedTokenInformation(name, symbol);
    }

    /**
    * Mint new tokens for the predefined inflation period and assign them to the reward wallet. 
    */
    function mintInflationPeriod() private {
        uint256 tokensToMint = totalSupply.mul(inflationCompBPS).div(10000);
        totalSupply = totalSupply.add(tokensToMint);
        balances[rewardWallet] = balances[rewardWallet].add(tokensToMint);
        Mint(rewardWallet, tokensToMint);
        Transfer(0x0, rewardWallet, tokensToMint);
    }     
    
    function setRewardWallet(address _rewardWallet) public onlyOwner {
        rewardWallet = _rewardWallet;
    }

    /**
    * Limit token transfer until the TGE is over.
    */
    modifier tokenReleased(address _sender) {
        require(released);
        _;
    }

    /**
    * This will make the tokens transferable
    */
    function releaseTokenTransfer() public onlyOwner {
        released = true;
    }

    // error: canTransfer(msg.sender, _value)
    function transfer(address _to, uint _value) public tokenReleased(msg.sender) intervalTrigger returns (bool success) {
        // Calls StandardToken.transfer()
        // error: super.transfer(_to, _value);
        return super.transfer(_to, _value);
    }

    function transferFrom(address _from, address _to, uint _value) public tokenReleased(_from) intervalTrigger returns (bool success) {
        // Calls StandardToken.transferForm()
        return super.transferFrom(_from, _to, _value);
    }

    function approve(address _spender, uint256 _value) public tokenReleased(msg.sender) intervalTrigger returns (bool) {
        // calls StandardToken.approve(..)
        return super.approve(_spender, _value);
    }

    function allowance(address _owner, address _spender) public constant returns (uint256 remaining) {
        // calls StandardToken.allowance(..)
        return super.allowance(_owner, _spender);
    }

    function increaseApproval (address _spender, uint _addedValue) public tokenReleased(msg.sender) intervalTrigger returns (bool success) {
        // calls StandardToken.increaseApproval(..)
        return super.increaseApproval(_spender, _addedValue);
    }

    function decreaseApproval (address _spender, uint _subtractedValue) public tokenReleased(msg.sender) intervalTrigger returns (bool success) {
        // calls StandardToken.decreaseApproval(..)
        return super.decreaseApproval(_spender, _subtractedValue);
    }
}
function LegalToken(address _rewardWallet, uint32 _inflationCompBPS, uint32 _inflationCompInterval) onlyOwner public {
    setTokenInformation("Legal Token", "LGL");
    totalSupply = 0;        
    rewardWallet = _rewardWallet;
    inflationCompBPS = _inflationCompBPS;
    registerIntervalCall(_inflationCompInterval, mintInflationPeriod);
}    

/**
 * @dev Constructor that gives msg.sender all of existing tokens. 
 */