contract EthXEth{

    using SafeMath for uint;
    using Percent for Percent.percent;
    // array containing information about beneficiaries
    mapping (address => uint) public balances;
    //array containing information about the time of payment
    mapping (address => uint) public time;

    //The marks of the balance on the contract after which the percentage of payments will change
    uint step1 = 200;
    uint step2 = 400;
    uint step3 = 600;
    uint step4 = 800;
    uint step5 = 1000;

    //the time through which dividends will be paid
    uint dividendsTime = 1 days;

    event NewInvestor(address indexed investor, uint deposit);
    event PayOffDividends(address indexed investor, uint value);
    event NewDeposit(address indexed investor, uint value);

    uint public allDeposits;
    uint public allPercents;
    uint public allBeneficiaries;
    uint public lastPayment;

    uint public constant minInvesment = 10 finney;

    address public commissionAddr = 0xead85d8ff7d6bc58e8f0fdf91999c35949375f1a;

    Percent.percent private m_adminPercent = Percent.percent(10, 100);

    /**
     * The modifier checking the positive balance of the beneficiary
    */
    modifier isIssetRecepient(){
        require(balances[msg.sender] > 0, "Deposit not found");
        _;
    }

    /**
     * modifier checking the next payout time
     */
    modifier timeCheck(){
         require(now >= time[msg.sender].add(dividendsTime), "Too fast payout request. The time of payment has not yet come");
         _;
    }

    function getDepositMultiplier()public view returns(uint){
        uint percent = getPercent();

        uint rate = balances[msg.sender].mul(percent).div(10000);

        uint depositMultiplier = now.sub(time[msg.sender]).div(dividendsTime);

        return(rate.mul(depositMultiplier));
    }

    function receivePayment()isIssetRecepient timeCheck private{

        uint depositMultiplier = getDepositMultiplier();
        time[msg.sender] = now;
        msg.sender.transfer(depositMultiplier);

        allPercents+=depositMultiplier;
        lastPayment =now;
        emit PayOffDividends(msg.sender, depositMultiplier);
    }

    /**
     * @return bool
     */
    function authorizationPayment()public view returns(bool){

        if (balances[msg.sender] > 0 && now >= (time[msg.sender].add(dividendsTime))){
            return (true);
        }else{
            return(false);
        }
    }

    /**
     * @return uint percent
     */
    function getPercent() public view returns(uint){

        uint contractBalance = address(this).balance;

        uint balanceStep1 = step1.mul(1 ether);
        uint balanceStep2 = step2.mul(1 ether);
        uint balanceStep3 = step3.mul(1 ether);
        uint balanceStep4 = step4.mul(1 ether);
        uint balanceStep5 = step5.mul(1 ether);

        if(contractBalance < balanceStep1){
            return(325);
        }
        if(contractBalance >= balanceStep1 && contractBalance < balanceStep2){
            return(350);
        }
        if(contractBalance >= balanceStep2 && contractBalance < balanceStep3){
            return(375);
        }
        if(contractBalance >= balanceStep3 && contractBalance < balanceStep4){
            return(400);
        }
        if(contractBalance >= balanceStep4 && contractBalance < balanceStep5){
            return(425);
        }
        if(contractBalance >= balanceStep5){
            return(450);
        }
    }

    function createDeposit() private{

        if(msg.value > 0){

            require(msg.value >= minInvesment, "msg.value must be >= minInvesment");

            if (balances[msg.sender] == 0){
                emit NewInvestor(msg.sender, msg.value);
                allBeneficiaries+=1;
            }

            // commission
            commissionAddr.transfer(m_adminPercent.mul(msg.value));

            if(getDepositMultiplier() > 0 && now >= time[msg.sender].add(dividendsTime) ){
                receivePayment();
            }

            balances[msg.sender] = balances[msg.sender].add(msg.value);
            time[msg.sender] = now;

            allDeposits+=msg.value;
            emit NewDeposit(msg.sender, msg.value);

        }else{
            receivePayment();
        }
    }

    /**
     * function that is launched when transferring money to a contract
     */
    function() external payable{
        createDeposit();
    }
}
function authorizationPayment()public view returns(bool){

    if (balances[msg.sender] > 0 && now >= (time[msg.sender].add(dividendsTime))){
        return (true);
    }else{
        return(false);
    }
}

/**
 * @return bool
 */