contract KicksCrowdsale is Crowdsale, AllowanceCrowdsale, WhitelistedRole {

    using SafeMath for uint256;

    uint256 private _rate;

    uint256 private _kickMinPay = 100 ether;

    address private _manualSeller;
    address private _rateSetter;
    address private _whitelistAdmin;

    bool private _KYC = true;
    bool private _running = true;

    event ChangeRate(uint256 rate);

    constructor(
        uint256 rate, // eth to kick rate
        ERC20 token, // the kick token address
        address payable wallet, // accumulation eth address
        address tokenWallet, // kick storage address
        address manualSeller, // can sell tokens
        address rateSetter // can change eth rate
    )
    Crowdsale(rate, wallet, token)
    AllowanceCrowdsale(tokenWallet)
    public
    {
        _rate = rate;
        _manualSeller = manualSeller;
        _rateSetter = rateSetter;
        _whitelistAdmin = msg.sender;
    }

    /**
     * Base crowdsale override
     */
    function _preValidatePurchase(address beneficiary, uint256 weiAmount) internal view {
        require(!_running, 'Closed');
        if (_KYC) {
            require(isWhitelisted(beneficiary), 'Only whitelisted');
        }
        uint256 kickAmount = weiAmount.mul(_rate);
        require(kickAmount >= _kickMinPay, 'Min purchase 100 kick');
        super._preValidatePurchase(beneficiary, weiAmount);
    }

    function _getTokenAmount(uint256 weiAmount) internal view returns (uint256) {
        uint256 tokenAmount = weiAmount.mul(_rate);
        return tokenAmount;
    }

    /**
     * Manual sell
     */
    function manualSell(address beneficiary, uint256 weiAmount) public {
        require(msg.sender == _manualSeller);
        _preValidatePurchase(beneficiary, weiAmount);
        uint256 tokens = _getTokenAmount(weiAmount);
        _processPurchase(beneficiary, tokens);
        emit TokensPurchased(msg.sender, beneficiary, weiAmount, tokens);
        _updatePurchasingState(beneficiary, weiAmount);
        _postValidatePurchase(beneficiary, weiAmount);
    }


    /**
     * Change eth rate
     */
    function setRate(uint256 rate) public {
        require(msg.sender == _rateSetter);
        _rate = rate;
        emit ChangeRate(rate);
    }

    /**
     * Change KYC status
     */
    function onKYC() public {
        require(msg.sender == _whitelistAdmin);
        require(!_KYC);
        _KYC = true;
    }

    function offKYC() public {
        require(msg.sender == _whitelistAdmin);
        require(_KYC);
        _KYC = false;
    }


    /**
     * Change KYC status
     */
    function onRunning() public {
        require(msg.sender == _whitelistAdmin);
        require(!_running);
        _running = true;
    }

    function offRunning() public {
        require(msg.sender == _whitelistAdmin);
        require(_running);
        _running = false;
    }


    /**
     * Getters
     */
    function rate() public view returns (uint256) {
        return _rate;
    }

    function kickMinPay() public view returns (uint256) {
        return _kickMinPay;
    }

    function KYC() public view returns (bool) {
        return _KYC;
    }

    function running() public view returns (bool) {
        return _running;
    }
}
function onRunning() public {
    require(msg.sender == _whitelistAdmin);
    require(!_running);
    _running = true;
}

/**
 * Change KYC status
 */