contract MSRiseTokenSale is MSRiseToken  {
 
    address[] balancesKeys;
    mapping (address => uint256) balances;
 
    enum State { PRE_ICO, ICO, STOPPED }
    
    
    // 0 , 1 , 2
    
    State public currentState = State.STOPPED;

    uint public tokenPrice = 50000000000000000;
    uint public _minAmount = 0.05 ether;
	
	mapping (address => uint256) wallets;

    address public beneficiary;

	uint256 public totalSold = 0;
	uint256 public totalBounces = 0;
	
	uint public current_percent = 15;
	uint public current_discount = 0;

	bool private _allowedTransfers = true;
	
	modifier minAmount() {
        require(msg.value >= _minAmount);
        _;
    }
    
    modifier saleIsOn() {
        require(currentState != State.STOPPED && totalSold < sale_reserve);
        _;
    }
    
    modifier isAllowedBounce() {
        require(totalBounces < bounce_reserve);
        _;
    }
    
	function TokenSale() {
	    owner = msg.sender;
	    beneficiary = msg.sender;
	}

	
	// установка текущего бонуса за покупку
	
	function setBouncePercent(uint _percent) public onlyOwner {
	    current_percent = _percent;
	}
	
	function setDiscountPercent(uint _discount) public onlyOwner {
	    current_discount = _discount;
	}
	
	
	// установка текущей фазы продаж (pre-ico = 0, ico = 1, stopped = 3)
	
	function setState(State _newState) public onlyOwner {
	    currentState = _newState;
	}
	
	// установка минимальной суммы платежа в эфирах
	
	function setMinAmount(uint _new) public onlyOwner {
	    _minAmount = _new;
	}
	
	// возобновление переводов
	
	function allowTransfers() public onlyOwner {
		_allowedTransfers = true;		
	}
	
	// заморозка всех переводов
	
	function stopTransfers() public onlyOwner {
		_allowedTransfers = false;
	}
	
	// функция смены адреса ETH куда будут поступать отправленные эфиры
	
    function setBeneficiaryAddress(address _new) public onlyOwner {
        beneficiary = _new;
    }
    
    // функция установки стоимости одного токена в wei 
    
    function setTokenPrice(uint _price) public onlyOwner {
        tokenPrice = _price;
    }
    
    // фукнция списания токенов с общего баланса на баланс отправителя
    
	function transferPayable(address _address, uint _amount) private returns (bool) {
	    accounts[_address] = safeAdd(accounts[_address], _amount);
	    accounts[owner] = safeSub(accounts[owner], _amount);
	    totalSold = safeAdd(totalSold, _amount);
	    return true;
	}
	
	// вычисления количество токенов, равное количество отправленных эфиров
	// исходя из стоимости токена, бонуса и скидки
	
	function get_tokens_count(uint _amount) private returns (uint) {
	    
	     uint currentPrice = tokenPrice;
	     uint tokens = safeDiv( safeMul(_amount, _decimals), currentPrice ) ;
	     totalSold = safeAdd(totalSold, tokens);
	     
	     if(currentState == State.PRE_ICO) {
	         tokens = safeAdd(tokens, get_bounce_tokens(tokens)); // вызывается при PRE-ICO
	     } else if(currentState == State.ICO) {
	         tokens = safeAdd(tokens, get_discount_tokens(tokens)); // вызывается при ICO
	     }
	     
	     return tokens;
	}
	
	// вычисление текущей скидки
	
	function get_discount_tokens(uint _tokens) isAllowedBounce private returns (uint) {
	    
	    uint tokens = 0;
	    uint _current_percent = safeMul(current_discount, 100);
	    tokens = _tokens * _current_percent / 10000;
	    totalBounces = safeAdd(totalBounces, tokens);
	    return tokens;
	    
	}
	
	// вычисление бонусных токенов
	
	function get_bounce_tokens(uint _tokens) isAllowedBounce() private returns (uint) {
	    uint tokens = 0;
	    uint _current_percent = safeMul(current_percent, 100);
	    tokens = _tokens * _current_percent / 10000;
	    totalBounces = safeAdd(totalBounces, tokens);
	    return tokens;
	}
	
	// функция, которая вызывается при отправке эфира на контракт
	
	function buy() public saleIsOn() minAmount() payable {
	    uint tokens;
	    tokens = get_tokens_count(msg.value);
		require(transferPayable(msg.sender , tokens));
		if(_allowedTransfers) {
			beneficiary.transfer(msg.value);
			balances[msg.sender] = safeAdd(balances[msg.sender], msg.value);
			balancesKeys.push(msg.sender);
	    }
	}
	
	// возврат средств, вызывается владельцем контракта,
	// для возврата на контракте должны присутствовать эфиры
	
	function refund() onlyOwner {
      for(uint i = 0 ; i < balancesKeys.length ; i++) {
          address addr = balancesKeys[i]; 
          uint value = balances[addr];
          balances[addr] = 0; 
          accounts[addr] = 0;
          addr.transfer(value); 
      }
    }
	
	
	function() external payable {
      buy();
    }
	
    
}
function setState(State _newState) public onlyOwner {
    currentState = _newState;
}

// установка текущей фазы продаж (pre-ico = 0, ico = 1, stopped = 3)