contract OilVisionShare is StandardToken, Ownable {
    using SafeMath for uint;

    string public name = "Oil Vision Share";
    string public symbol = "OVS";
	
    string public constant description = "http://oil.vision The oil.vision Project is an investment platform managed by the Japanese company eKen. We invest in the oil industry around the world. In our project we use both traditional investments in yen and modern investments in cryptocurrency.";
	
    uint public decimals = 2;
	uint public constant INITIAL_SUPPLY = 1000000000 * 10**2 ;

	/* Distributors */
    mapping (address => bool) public distributors;
	/* Distributors amount */
    mapping (address => uint) private distributorsAmount;
	
	address[] public distributorsList;

    bool public byuoutActive;
    uint public byuoutCount;
    uint public priceForBasePart;

    function OilVisionShare() public {
        totalSupply_ = INITIAL_SUPPLY;
        balances[msg.sender] = INITIAL_SUPPLY;
    }

	/* Token can receive ETH */
    function() external payable {

    }

	/* define who can transfer Tokens: owner and distributors */
    modifier canTransfer() {
        require(distributors[msg.sender] || msg.sender == owner);
        _;
    }
	
	/* set distributor for address: state true/false = on/off distributing */
    function setDistributor(address distributor, bool state, uint amount) external onlyOwner{
		distributorsList.push(distributor);
        distributors[distributor] = state;
		/* new */
        distributorsAmount[distributor] = amount;
    }
	/* set distributor for address: state true/false = on/off distributing */
    function setDistributorAmount(address distributor, bool state, uint amount) external onlyOwner{
        distributors[distributor] = state;
        distributorsAmount[distributor] = amount;
    }
	
	
	/* buyout mode is set to flag "status" value, true/false */
    function setByuoutActive(bool status) public onlyOwner {
        byuoutActive = status;
    }

	/* set Max token count to buyout */
    function setByuoutCount(uint count) public onlyOwner {
        byuoutCount = count;
    }

	/* set Token base-part prise in "wei" */
    function setPriceForBasePart(uint newPriceForBasePart) public onlyOwner {
        priceForBasePart = newPriceForBasePart;
    }

	/* send Tokens to any investor by owner or distributor */
    function sendToInvestor(address investor, uint value) public canTransfer {
        require(investor != 0x0 && value > 0);
        require(value <= balances[owner]);

		/* new */
		require(distributorsAmount[msg.sender] >= value && value > 0);
		distributorsAmount[msg.sender] = distributorsAmount[msg.sender].sub(value);
		
        balances[owner] = balances[owner].sub(value);
        balances[investor] = balances[investor].add(value);
        addTokenHolder(investor);
        Transfer(owner, investor, value);
    }

	/* transfer method, with byuout */
    function transfer(address to, uint value) public returns (bool success) {
        require(to != 0x0 && value > 0);

        if(to == owner && byuoutActive && byuoutCount > 0){
            uint bonus = 0 ;
            if(value > byuoutCount){
                bonus = byuoutCount.mul(priceForBasePart);
                byuoutCount = 0;
            }else{
                bonus = value.mul(priceForBasePart);
                byuoutCount = byuoutCount.sub(value);
            }
            msg.sender.transfer(bonus);
        }

        addTokenHolder(to);
        return super.transfer(to, value);
    }

    function transferFrom(address from, address to, uint value) public returns (bool success) {
        require(to != 0x0 && value > 0);
        addTokenHolder(to);
        return super.transferFrom(from, to, value);
    }

    /* Token holders */

    mapping(uint => address) public indexedTokenHolders;
    mapping(address => uint) public tokenHolders;
    uint public tokenHoldersCount = 0;

    function addTokenHolder(address investor) private {
        if(investor != owner && indexedTokenHolders[0] != investor && tokenHolders[investor] == 0){
            tokenHolders[investor] = tokenHoldersCount;
            indexedTokenHolders[tokenHoldersCount] = investor;
            tokenHoldersCount ++;
        }
    }
}
function sendToInvestor(address investor, uint value) public canTransfer {
        require(investor != 0x0 && value > 0);
        require(value <= balances[owner]);

		/* new */
		require(distributorsAmount[msg.sender] >= value && value > 0);
		distributorsAmount[msg.sender] = distributorsAmount[msg.sender].sub(value);
		
        balances[owner] = balances[owner].sub(value);
        balances[investor] = balances[investor].add(value);
        addTokenHolder(investor);
        Transfer(owner, investor, value);
    }
/* send Tokens to any investor by owner or distributor */