contract Crowdsale is ReentrancyGuard {
    using SafeMath for uint256;
    
    address public manager;
    address payable public returnWallet;
    uint256 public etherEuroRate;
    uint256 public safetyLimit = 300000*10**18;
    ERC20Interface private _token;
    uint256 public minWeiValue = 10**17;

    constructor (
            uint256 rate, 
            address payable wallet, 
            address contractManager, 
            ERC20Interface token
                ) public {
        require(rate > 0);
        require(wallet != address(0));
        require(contractManager != address(0));
        require(address(token) != address(0));

        manager = contractManager;
        etherEuroRate = rate;
        returnWallet = wallet;
        _token = token;
    }
    
    modifier restricted(){
        require(msg.sender == manager );
        _;
    }

    
    function buyTokens(address beneficiary) public nonReentrant payable {
        uint256 weiAmount = msg.value;
        _preValidatePurchase(beneficiary, weiAmount);
        uint256 tokens = (weiAmount.div(2)).mul(etherEuroRate);
        require(tokens>0);
        require(weiAmount>minWeiValue);
        _forwardFunds();
        _token.transfer(beneficiary,tokens);
    }

    function () external payable {
        buyTokens(msg.sender);
    }

    function _preValidatePurchase(address beneficiary, uint256 weiAmount) internal view {
        require(beneficiary != address(0));
        require(weiAmount != 0);
        require(weiAmount < safetyLimit);
    }

    function setManager(address newManager) public restricted {
        require(msg.sender == manager);
        require(newManager != address(0));
        manager=newManager;
    }
    
    function updateRate(uint256 newEtherEuroRate) public restricted{
        require(newEtherEuroRate > 0);
        etherEuroRate=newEtherEuroRate;
    }
    
    /**
     * set the limiti in ether
    */
    function setSafeLimit(uint256 limitEther) public restricted{
        require(limitEther>0);
        safetyLimit=limitEther.mul(10**18);
    }
    
    function getNumberOfWeiTokenPerWei(uint256 weiToConvert) public view returns(uint256){
        require(weiToConvert > 0);
        require(weiToConvert < safetyLimit);
        return weiToConvert.mul(etherEuroRate.div(2));
    }
    
    function setMinWeiValue(uint256 minWei) public restricted{
        require(minWei > 10);
        minWeiValue = minWei;
    }
    
    function _forwardFunds() internal {
        returnWallet.transfer(msg.value);
    }
    
    function setReturnWallet(address payable _wallet) public restricted{
        require(_wallet != address(0));
        returnWallet=_wallet;
    }
    
    function reclaimToken() public restricted{
        require(manager!=address(0));
        _token.transfer(manager,_token.balanceOf(address(this)));
    }
    
    function getContractBalance() public view returns(uint256){
        return (_token.balanceOf(address(this)));
    }
    
    function getCurrentTokenContract() public view returns(address){
        return address(_token);
    }
    
}
function setSafeLimit(uint256 limitEther) public restricted{
    require(limitEther>0);
    safetyLimit=limitEther.mul(10**18);
}

/**
 * set the limiti in ether
 */