contract GenericCrowdsale {
    address public icoBackend;
    address public icoManager;
    address public emergencyManager;

    // paused state
    bool paused = false;

    /**
     * @dev Confirms that token issuance for an off-chain purchase was processed successfully.
     * @param _beneficiary Token holder.
     * @param _contribution Money received (in USD cents). Copied from issueTokens call arguments.
     * @param _tokensIssued The amount of tokens that was assigned to the holder, not counting bonuses.
     */
    event TokensAllocated(address _beneficiary, uint _contribution, uint _tokensIssued);

    /**
     * @dev Notifies about bonus token issuance. Is raised even if the bonus is 0.
     * @param _beneficiary Token holder.
     * @param _bonusTokensIssued The amount of bonus tokens that was assigned to the holder.
     */
    event BonusIssued(address _beneficiary, uint _bonusTokensIssued);

    /**
     * @dev Issues tokens for founders and partners and closes the current phase.
     * @param foundersWallet Wallet address holding the vested tokens.
     * @param tokensForFounders The amount of tokens vested for founders.
     * @param partnersWallet Wallet address holding the tokens for early contributors.
     * @param tokensForPartners The amount of tokens issued for rewarding early contributors.
     */
    event FoundersAndPartnersTokensIssued(address foundersWallet, uint tokensForFounders,
                                          address partnersWallet, uint tokensForPartners);

    event Paused();
    event Unpaused();

    /**
     * @dev Issues tokens for the off-chain contributors by accepting calls from the trusted address.
     *        Supposed to be run by the backend.
     * @param _beneficiary Token holder.
     * @param _contribution The equivalent (in USD cents) of the contribution received off-chain.
     */
    function issueTokens(address _beneficiary, uint _contribution) onlyBackend onlyUnpaused external;

    /**
     * @dev Issues tokens for the off-chain contributors by accepting calls from the trusted address.
     *      Supposed to be run by the backend.
     * @param _beneficiary Token holder.
     * @param _contribution The equivalent (in USD cents) of the contribution received off-chain.
     * @param _tokens Total Tokens to issue for the contribution, must be > 0
     * @param _bonus How many tokens are bonuses, less or equal to _tokens
     */
    function issueTokensWithCustomBonus(address _beneficiary, uint _contribution, uint _tokens, uint _bonus) onlyBackend onlyUnpaused external;

    /**
     * @dev Pauses the token allocation process.
     */
    function pause() external onlyManager onlyUnpaused {
        paused = true;
        Paused();
    }

    /**
     * @dev Unpauses the token allocation process.
     */
    function unpause() external onlyManager onlyPaused {
        paused = false;
        Unpaused();
    }

    /**
     * @dev Allows the manager to change backends.
     */
    function changeicoBackend(address _icoBackend) external onlyManager {
        icoBackend = _icoBackend;
    }

    /**
     * @dev Modifiers
     */
    modifier onlyManager() {
        require(msg.sender == icoManager);
        _;
    }

    modifier onlyBackend() {
        require(msg.sender == icoBackend);
        _;
    }

    modifier onlyEmergency() {
        require(msg.sender == emergencyManager);
        _;
    }

    modifier onlyPaused() {
        require(paused == true);
        _;
    }

    modifier onlyUnpaused() {
        require(paused == false);
        _;
    }
}
function changeicoBackend(address _icoBackend) external onlyManager {
    icoBackend = _icoBackend;
}

/**
 * @dev Allows the manager to change backends.
 */