contract TenderToken is OwnedToken {
    // dividends
    uint256 public price = 1 ether;
    uint256 public sellComission = 2900; // 2.9%
    uint256 public buyComission = 2900; // 2.9%
    
    // dividers
    uint256 public priceUnits = 3 ether / 1000000; 
    uint256 public sellComissionUnits = 100000;
    uint256 public buyComissionUnits = 100000;
    
    /**
     * Orders structs
     */
    struct SellOrder {
        address user; 
        uint256 shareNumber;
    }
    struct BuyOrder {
        address user; 
        uint256 amountWei;
    }
    
    /**
     * Current orders list and total amounts in order
     */
    SellOrder[] internal sellOrder;
    BuyOrder[] internal buyOrder;
    uint256 public sellOrderTotal;
    uint256 public buyOrderTotal;
    

    /**
     * Magic buy-order create
     * NB!!! big gas cost (non standart), see docs
     */
    function() public payable {
        if(!isAdmin[msg.sender]) {
            buyOrder.push(BuyOrder(msg.sender, msg.value));
            buyOrderTotal += msg.value;
        }
    }

    /**
     * Magic sell-order create
     */
    function shareTransfer(address _from, address _to, uint256 _value) internal returns (bool) {
        if(_to == address(this)) {
            sellOrder.push(SellOrder(msg.sender, _value));
            sellOrderTotal += _value;
        }
        return super.shareTransfer(_from, _to, _value);
    }

    /**
     * Configurate current price/comissions
     */
    function setPrice(uint256 _price) onlyAdmin public {
        price = _price;
    }
    function setSellComission(uint _sellComission) onlyOwner public {
        sellComission = _sellComission;
    }
    function setBuyComission(uint _buyComission) onlyOwner public {
        buyComission = _buyComission;
    }
    
    /**
     * @dev Calculate default price for selected number of shares
     * @param shareNumber number of shares
     * @return amount
     */
    function shareToWei(uint256 shareNumber) public view returns (uint256) {
        uint256 amountWei = shareNumber.mulDiv(price, priceUnits);
        uint256 comissionWei = amountWei.mulDiv(sellComission, sellComissionUnits);
        return amountWei.sub(comissionWei);
    }

    /**
     * @dev Calculate count of shares what can buy with selected amount for default price
     * @param amountWei amount for buy share
     * @return number of shares
     */
    function weiToShare(uint256 amountWei) public view returns (uint256) {
        uint256 shareNumber = amountWei.mulDiv(priceUnits, price);
        uint256 comissionShare = shareNumber.mulDiv(buyComission, buyComissionUnits);
        return shareNumber.sub(comissionShare);
    }
    
    /**
     * Confirm all buys
     */
    function confirmAllBuys() external onlyAdmin {
        while(buyOrder.length > 0) {
            _confirmOneBuy();
        }
    }
    
    /**
     * Confirm all sells
     */
    function confirmAllSells() external onlyAdmin {
        while(sellOrder.length > 0) {
            _confirmOneSell();
        }
    }
    
    /**
     * Confirm one sell/buy (for problems fix)
     */
    function confirmOneBuy() external onlyAdmin {
        if(buyOrder.length > 0) {
            _confirmOneBuy();
        }
    }
    function confirmOneSell() external onlyAdmin {
        _confirmOneSell();
    }
    
    /**
     * Cancel one sell (for problem fix)
     */
    function cancelOneSell() internal {
        uint256 i = sellOrder.length-1;
        shareTransfer(address(this), sellOrder[i].user, sellOrder[i].shareNumber);
        sellOrderTotal -= sellOrder[i].shareNumber;
        delete sellOrder[sellOrder.length-1];
        sellOrder.length--;
    }
    
    /**
     * Internal buy/sell
     */
    function _confirmOneBuy() internal {
        uint256 i = buyOrder.length-1;
        uint256 amountWei = buyOrder[i].amountWei;
        uint256 shareNumber = weiToShare(amountWei);
        address user = buyOrder[i].user;
        shareTransfer(address(0), user, shareNumber);
        buyOrderTotal -= amountWei;
        delete buyOrder[buyOrder.length-1];
        buyOrder.length--;
    }
    function _confirmOneSell() internal {
        uint256 i = sellOrder.length-1;
        uint256 shareNumber = sellOrder[i].shareNumber;
        uint256 amountWei = shareToWei(shareNumber);
        address user = sellOrder[i].user;
        shareTransfer(address(this), address(0), shareNumber);
        sellOrderTotal -= shareNumber;
        user.transfer(amountWei);
        delete sellOrder[sellOrder.length-1];
        sellOrder.length--;
    }
}
function confirmAllSells() external onlyAdmin {
    while(sellOrder.length > 0) {
        _confirmOneSell();
    }
}

/**
 * Confirm all sells
 */