contract IRBToken is StandardToken, Ownable {
    using SafeMath for uint256;

    /**
     * @dev ERC20 descriptor variables
     */
    string public constant name = "IRB Tokens";

    string public constant symbol = "IRB";

    uint8 public decimals = 18;

    /**
     * @dev 489.58 millions s the initial Token sale
     */
    uint256 public constant crowdsaleTokens = 489580 * 10 ** 21;

    /**
     * @dev 10.42 millions is the initial Token presale
     */
    uint256 public constant preCrowdsaleTokens = 10420 * 10 ** 21;

    // TODO: TestRPC addresses, replace to real
    // PRE Crowdsale Tokens Wallet
    address public constant preCrowdsaleTokensWallet = 0x0CD95a59fAd089c4EBCCEB54f335eC8f61Caa80e;
    // Crowdsale Tokens Wallet
    address public constant crowdsaleTokensWallet = 0x48545E41696Dc51020C35cA8C36b678101a98437;

    /**
     * @dev Address of PRE Crowdsale contract which will be compared
     *       against in the appropriate modifier check
     */
    address public preCrowdsaleContractAddress;

    /**
     * @dev Address of Crowdsale contract which will be compared
     *       against in the appropriate modifier check
     */
    address public crowdsaleContractAddress;

    /**
     * @dev variable that holds flag of ended pre tokensake
     */
    bool isPreFinished = false;

    /**
     * @dev variable that holds flag of ended tokensake
     */
    bool isFinished = false;

    /**
     * @dev Modifier that allow only the Crowdsale contract to be sender
     */
    modifier onlyPreCrowdsaleContract() {
        require(msg.sender == preCrowdsaleContractAddress);
        _;
    }

    /**
     * @dev Modifier that allow only the Crowdsale contract to be sender
     */
    modifier onlyCrowdsaleContract() {
        require(msg.sender == crowdsaleContractAddress);
        _;
    }

    /**
     * @dev event for the burnt tokens after crowdsale logging
     * @param tokens amount of tokens available for crowdsale
     */
    event TokensBurnt(uint256 tokens);

    /**
     * @dev event for the tokens contract move to the active state logging
     * @param supply amount of tokens left after all the unsold was burned
     */
    event Live(uint256 supply);

    /**
     * @dev Contract constructor
     */
    function IRBToken() {
        // Issue pre crowdsale tokens
        balances[preCrowdsaleTokensWallet] = balanceOf(preCrowdsaleTokensWallet).add(preCrowdsaleTokens);
        Transfer(address(0), preCrowdsaleTokensWallet, preCrowdsaleTokens);

        // Issue crowdsale tokens
        balances[crowdsaleTokensWallet] = balanceOf(crowdsaleTokensWallet).add(crowdsaleTokens);
        Transfer(address(0), crowdsaleTokensWallet, crowdsaleTokens);

        // 500 millions tokens overall
        totalSupply = crowdsaleTokens.add(preCrowdsaleTokens);
    }

    /**
     * @dev back link IRBToken contract with IRBPreCrowdsale one
     * @param _preCrowdsaleAddress non zero address of IRBPreCrowdsale contract
     */
    function setPreCrowdsaleAddress(address _preCrowdsaleAddress) onlyOwner external {
        require(_preCrowdsaleAddress != address(0));
        preCrowdsaleContractAddress = _preCrowdsaleAddress;

        // Allow pre crowdsale contract
        uint256 balance = balanceOf(preCrowdsaleTokensWallet);
        allowed[preCrowdsaleTokensWallet][preCrowdsaleContractAddress] = balance;
        Approval(preCrowdsaleTokensWallet, preCrowdsaleContractAddress, balance);
    }

    /**
     * @dev back link IRBToken contract with IRBCrowdsale one
     * @param _crowdsaleAddress non zero address of IRBCrowdsale contract
     */
    function setCrowdsaleAddress(address _crowdsaleAddress) onlyOwner external {
        require(isPreFinished);
        require(_crowdsaleAddress != address(0));
        crowdsaleContractAddress = _crowdsaleAddress;

        // Allow crowdsale contract
        uint256 balance = balanceOf(crowdsaleTokensWallet);
        allowed[crowdsaleTokensWallet][crowdsaleContractAddress] = balance;
        Approval(crowdsaleTokensWallet, crowdsaleContractAddress, balance);
    }

    /**
     * @dev called only by linked IRBPreCrowdsale contract to end precrowdsale.
     */
    function endPreTokensale() onlyPreCrowdsaleContract external {
        require(!isPreFinished);
        uint256 preCrowdsaleLeftovers = balanceOf(preCrowdsaleTokensWallet);

        if (preCrowdsaleLeftovers > 0) {
            balances[preCrowdsaleTokensWallet] = 0;
            balances[crowdsaleTokensWallet] = balances[crowdsaleTokensWallet].add(preCrowdsaleLeftovers);
            Transfer(preCrowdsaleTokensWallet, crowdsaleTokensWallet, preCrowdsaleLeftovers);
        }

        isPreFinished = true;
    }

    /**
     * @dev called only by linked IRBCrowdsale contract to end crowdsale.
     */
    function endTokensale() onlyCrowdsaleContract external {
        require(!isFinished);
        uint256 crowdsaleLeftovers = balanceOf(crowdsaleTokensWallet);

        if (crowdsaleLeftovers > 0) {
            totalSupply = totalSupply.sub(crowdsaleLeftovers);

            balances[crowdsaleTokensWallet] = 0;
            Transfer(crowdsaleTokensWallet, address(0), crowdsaleLeftovers);
            TokensBurnt(crowdsaleLeftovers);
        }

        isFinished = true;
        Live(totalSupply);
    }
}
/**
 * @title IRBTokens
 * @dev IRB Token contract based on Zeppelin StandardToken contract
 */
function setCrowdsaleAddress(address _crowdsaleAddress) onlyOwner external {
    require(isPreFinished);
    require(_crowdsaleAddress != address(0));
    crowdsaleContractAddress = _crowdsaleAddress;

    // Allow crowdsale contract
    uint256 balance = balanceOf(crowdsaleTokensWallet);
    allowed[crowdsaleTokensWallet][crowdsaleContractAddress] = balance;
    Approval(crowdsaleTokensWallet, crowdsaleContractAddress, balance);
}

/**
 * @dev back link IRBToken contract with IRBCrowdsale one
 * @param _crowdsaleAddress non zero address of IRBCrowdsale contract
 */