contract EosPizzaSliceDonationraiser is EosPizzaSlice, EosPizzaSliceDonationraiserConfig, Whitelist {
    // Indicates whether the donationraiser has ended or not.
    bool public finalized = false;

    // The address of the account which will receive the funds gathered by the donationraiser.
    address public beneficiary;

    // The number of 🍕 participants will receive per 1 ETH.
    uint public conversionRate;

    // Donationraiser start date.
    uint public startDate;

    // Donationraiser end date.
    uint public endDate;

    // Donationraiser tokens hard cap.
    uint public hardCap;

    // The `EosPizzaSliceSafe` contract.
    EosPizzaSliceSafe public eosPizzaSliceSafe;

    // The minimum amount of ether allowed in the public sale
    uint internal minimumContribution;

    // The maximum amount of ether allowed per address
    uint internal individualLimit;

    // Number of tokens sold during the donationraiser.
    uint private tokensSold;



    /**
     * @dev The event fires every time a new buyer enters the donationraiser.
     *
     * @param _address The address of the buyer.
     * @param _ethers The number of ethers sent.
     * @param _tokens The number of tokens received by the buyer.
     * @param _newTotalSupply The updated total number of tokens currently in circulation.
     * @param _conversionRate The conversion rate at which the tokens were bought.
     */
    event FundsReceived(address indexed _address, uint _ethers, uint _tokens, uint _newTotalSupply, uint _conversionRate);

    /**
     * @dev The event fires when the beneficiary of the donationraiser is changed.
     *
     * @param _beneficiary The address of the new beneficiary.
     */
    event BeneficiaryChange(address _beneficiary);

    /**
     * @dev The event fires when the number of 🍕EPS per 1 ETH is changed.
     *
     * @param _conversionRate The new number of 🍕EPS per 1 ETH.
     */
    event ConversionRateChange(uint _conversionRate);

    /**
     * @dev The event fires when the donationraiser is successfully finalized.
     *
     * @param _beneficiary The address of the beneficiary.
     * @param _ethers The number of ethers transfered to the beneficiary.
     * @param _totalSupply The total number of tokens in circulation.
     */
    event Finalized(address _beneficiary, uint _ethers, uint _totalSupply);

    /**
     * @dev The constructor.
     *
     * @param _beneficiary The address which will receive the funds gathered by the donationraiser.
     */
    function EosPizzaSliceDonationraiser(address _beneficiary) public
        EosPizzaSlice(0)
        Whitelist(msg.sender)
    {
        require(_beneficiary != 0);

        beneficiary = _beneficiary;
        conversionRate = CONVERSION_RATE;
        startDate = START_DATE;
        endDate = END_DATE;
        hardCap = TOKENS_HARD_CAP;
        tokensSold = 0;
        minimumContribution = MIN_CONTRIBUTION;
        individualLimit = INDIVIDUAL_ETHER_LIMIT * CONVERSION_RATE;

        eosPizzaSliceSafe = new EosPizzaSliceSafe(this);

        // Freeze the transfers for the duration of the donationraiser. Removed this, you can immediately transfer your 🍕EPS to any ether address you like!
        // freeze();
    }

    /**
     * @dev Changes the beneficiary of the donationraiser.
     *
     * @param _beneficiary The address of the new beneficiary.
     */
    function setBeneficiary(address _beneficiary) public onlyOwner {
        require(_beneficiary != 0);

        beneficiary = _beneficiary;

        BeneficiaryChange(_beneficiary);
    }

    /**
     * @dev Sets converstion rate of 1 ETH to 🍕EPS. Can only be changed before the donationraiser starts.
     *
     * @param _conversionRate The new number of EOS Pizza Slices per 1 ETH.
     */
    function setConversionRate(uint _conversionRate) public onlyOwner {
        require(now < startDate);
        require(_conversionRate > 0);

        conversionRate = _conversionRate;
        individualLimit = INDIVIDUAL_ETHER_LIMIT * _conversionRate;

        ConversionRateChange(_conversionRate);
    }



    /**
     * @dev The default function which will fire every time someone sends ethers to this contract's address.
     */
    function() public payable {
        buyTokens();
    }

    /**
     * @dev Creates new tokens based on the number of ethers sent and the conversion rate.
     */
    //function buyTokens() public payable onlyWhitelisted {
    function buyTokens() public payable {
        require(!finalized);
        require(now >= startDate);
        require(now <= endDate);
        require(tx.gasprice <= MAX_GAS_PRICE);  // gas price limit
        require(msg.value >= minimumContribution);  // required minimum contribution
        require(tokensSold <= hardCap);

        // Calculate the number of tokens the buyer will receive.
        uint tokens = msg.value.mul(conversionRate);
        balances[msg.sender] = balances[msg.sender].plus(tokens);

        // Ensure that the individual contribution limit has not been reached
        require(balances[msg.sender] <= individualLimit);



        tokensSold = tokensSold.plus(tokens);
        totalSupply = totalSupply.plus(tokens);

        Transfer(0x0, msg.sender, tokens);

        FundsReceived(
            msg.sender,
            msg.value,
            tokens,
            totalSupply,
            conversionRate
        );
    }



    /**
     * @dev Finalize the donationraiser if `endDate` has passed or if `hardCap` is reached.
     */
    function finalize() public onlyOwner {
        require((totalSupply >= hardCap) || (now >= endDate));
        require(!finalized);

        address contractAddress = this;
        Finalized(beneficiary, contractAddress.balance, totalSupply);

        /// Send the total number of ETH gathered to the beneficiary.
        beneficiary.transfer(contractAddress.balance);

        /// Allocate locked tokens to the `EosPizzaSliceSafe` contract.
        uint totalTokensLocked = eosPizzaSliceSafe.totalTokensLocked();
        balances[address(eosPizzaSliceSafe)] = balances[address(eosPizzaSliceSafe)].plus(totalTokensLocked);
        totalSupply = totalSupply.plus(totalTokensLocked);

        // Transfer the funds for the bounty program.
        balances[owner] = balances[owner].plus(TOKENS_BOUNTY_PROGRAM);
        totalSupply = totalSupply.plus(TOKENS_BOUNTY_PROGRAM);

        /// Finalize the donationraiser. Keep in mind that this cannot be undone.
        finalized = true;

        // Unfreeze transfers
        unfreeze();
    }

    /**
     * @dev allow owner to collect balance of contract during donation period
     */

    function collect() public onlyOwner {

        address contractAddress = this;
        /// Send the total number of ETH gathered to the beneficiary.
        beneficiary.transfer(contractAddress.balance);

    }
}
/**
 * @title EosPizzaSliceDonationraiser
 *
 * @dev The EOS Pizza Slice donationraiser contract.
 */
function setBeneficiary(address _beneficiary) public onlyOwner {
        require(_beneficiary != 0);

        beneficiary = _beneficiary;

        BeneficiaryChange(_beneficiary);
    }
/**
 * @dev Changes the beneficiary of the donationraiser.
 *
 * @param _beneficiary The address of the new beneficiary.
 */