contract Crowdsale is Ownable {
    using SafeMath for uint256;
    using SafeERC20 for ERC20;

    // The token being sold
    ERC20 public token;

    // Address where funds are collected
    address public wallet;

    // How many token units a buyer gets per wei.
    // The rate is the conversion between wei and the smallest and indivisible token unit.
    // So, if you are using a rate of 1 with a DetailedERC20 token with 3 decimals called TOK
    // 1 wei will give you 1 unit, or 0.001 TOK.
    uint256 public rate;
    uint256 public preSaleRate;
    uint256 minPurchase = 10000000000000000;
    uint256 tokenSold;

    // Amount of wei raised
    uint256 public weiRaised;

    bool public isPreSale = false;
    bool public isICO = false;

    /**
     * Event for token purchase logging
     * @param purchaser who paid for the tokens
     * @param beneficiary who got the tokens
     * @param value weis paid for purchase
     * @param amount amount of tokens purchased
     */
    event TokenPurchase(address indexed purchaser, address indexed beneficiary, uint256 value, uint256 amount);
    event Finalized();
    /**
     * @dev Reverts if not in crowdsale time range.
     */
    modifier onlyWhileOpen {
        // solium-disable-next-line security/no-block-members
        require(isPreSale || isICO);
        _;
    }


    constructor(uint256 _rate, uint256 _preSaleRate, address _wallet, address _token) public {
        require(_rate > 0);
        require(_preSaleRate > 0);
        require(_wallet != address(0));
        require(_token != address(0));

        preSaleRate = _preSaleRate;
        rate = _rate;
        wallet = _wallet;
        token = ERC20(_token);
    }

    // -----------------------------------------
    // Crowdsale external interface
    // -----------------------------------------

    /**
     * @dev fallback function ***DO NOT OVERRIDE***
     */
    function () external payable {
        buyTokens(msg.sender);
    }

    /**
     * @dev low level token purchase ***DO NOT OVERRIDE***
     * @param _beneficiary Address performing the token purchase
     */
    function buyTokens(address _beneficiary) public payable {
        uint256 weiAmount = msg.value;
        _preValidatePurchase(_beneficiary, weiAmount);

        // calculate token amount to be created
        uint256 tokens = _getTokenAmount(weiAmount);
        _postValidatePurchase(tokens);

        // update state
        tokenSold = tokenSold.add(tokens);

        _processPurchase(_beneficiary, tokens);
        emit TokenPurchase(msg.sender, _beneficiary, weiAmount, tokens);

        _forwardFunds();
    }


    function manualSale(address _beneficiary, uint256 _amount) onlyOwner external {
        _processPurchase(_beneficiary, _amount);
    }

    // -----------------------------------------
    // Internal interface (extensible)
    // -----------------------------------------

    /**
     * @dev Validation of an incoming purchase. Use require statements to revert state when conditions are not met. Use super to concatenate validations.
     * @param _beneficiary Address performing the token purchase
     * @param _weiAmount Value in wei involved in the purchase
     */
    function _preValidatePurchase(address _beneficiary, uint256 _weiAmount) onlyWhileOpen internal view {
        require(_beneficiary != address(0));
        require(_weiAmount >= minPurchase);
    }


    function _postValidatePurchase(uint256 _tokens) internal view {
        if (isPreSale) {
            require(tokenSold.add(_tokens) <= 200000000 ether);
        }

    }

    /**
     * @dev Source of tokens. Override this method to modify the way in which the crowdsale ultimately gets and sends its tokens.
     * @param _beneficiary Address performing the token purchase
     * @param _tokenAmount Number of tokens to be emitted
     */
    function _deliverTokens(address _beneficiary, uint256 _tokenAmount) internal {
        token.safeTransfer(_beneficiary, _tokenAmount);
    }

    /**
     * @dev Executed when a purchase has been validated and is ready to be executed. Not necessarily emits/sends tokens.
     * @param _beneficiary Address receiving the tokens
     * @param _tokenAmount Number of tokens to be purchased
     */
    function _processPurchase(address _beneficiary, uint256 _tokenAmount) internal {
        _deliverTokens(_beneficiary, _tokenAmount);
    }

    /**
     * @dev Override to extend the way in which ether is converted to tokens.
     * @param _weiAmount Value in wei to be converted into tokens
     * @return Number of tokens that can be purchased with the specified _weiAmount
     */
    function _getTokenAmount(uint256 _weiAmount) internal view returns (uint256) {
        if (isPreSale) return _weiAmount.mul(preSaleRate);
        if (isICO) return _weiAmount.mul(rate);
        return 0;
    }

    /**
     * @dev Determines how ETH is stored/forwarded on purchases.
     */
    function _forwardFunds() internal {
        wallet.transfer(msg.value);
    }

    /**
     * @dev Must be called after crowdsale ends, to do some extra finalization
     * work. Calls the contract's finalization function.
     */
    function finalize() onlyOwner public {
        finalization();
        emit Finalized();
    }

    /**
     * @dev Can be overridden to add finalization logic. The overriding function
     * should call super.finalization() to ensure the chain of finalization is
     * executed entirely.
     */
    function finalization() internal {
        token.safeTransfer(msg.sender, token.balanceOf(this));
    }


    function setRate(uint _rate) onlyOwner external {
        rate = _rate;
    }

    function setPreSaleRate(uint _rate) onlyOwner external {
        preSaleRate = _rate;
    }


    function setPresaleStatus(bool _status) onlyOwner external {
        isPreSale = _status;
    }

    function setICOStatus(bool _status) onlyOwner external {
        isICO = _status;
    }

    function setMinPurchase(uint _val) onlyOwner external {
        minPurchase = _val;
    }
}
/**
 * @title Crowdsale
 * @dev Crowdsale is a base contract for managing a token crowdsale,
 * allowing investors to purchase tokens with ether. This contract implements
 * such functionality in its most fundamental form and can be extended to provide additional
 * functionality and/or custom behavior.
 * The external interface represents the basic interface for purchasing tokens, and conform
 * the base architecture for crowdsales. They are *not* intended to be modified / overriden.
 * The internal interface conforms the extensible and modifiable surface of crowdsales. Override
 * the methods to add functionality. Consider using 'super' where appropiate to concatenate
 * behavior.
 */
function _preValidatePurchase(address _beneficiary, uint256 _weiAmount) onlyWhileOpen internal view {
    require(_beneficiary != address(0));
    require(_weiAmount >= minPurchase);
}

/**
 * @dev Validation of an incoming purchase. Use require statements to revert state when conditions are not met. Use super to concatenate validations.
 * @param _beneficiary Address performing the token purchase
 * @param _weiAmount Value in wei involved in the purchase
 */