contract LogicContract is Ownable {

    /* ------ EVENTS ------ */

    event ShipWasBought(uint256 shipId);

    EternalStorageInterface private eternalStorageContract;
    ItemsStorageInterface private itemsStorageContract;

    constructor() public {
        eternalStorageContract = EternalStorageInterface(0x89eB6e29d81B98A4b88111e0d82924E6CBDc4AE4);
        itemsStorageContract = ItemsStorageInterface(0xf1fd447DAc5AbEAba356cD0010Bac95daA37C265);
    }

    /* ------ MODIFIERS ------ */

    modifier addressIsNotNull(address _newOwner) {
		require(_newOwner != address(0));
		_;
	}

    /* ------ FUNCTIONALITY FUNCTIONS ------ */

    function destroyLogicContract() public onlyOwner {
        selfdestruct(0xd135377eB20666725D518c967F23e168045Ee11F);
    }

    // Buying new ship
	function buyShip(uint256 _shipId, address _referrerWalletAddress) public payable addressIsNotNull(msg.sender)  {
        uint256 referrerPrize = 0;

        uint256 price = eternalStorageContract.getItemPriceById("ships", _shipId);
        require(msg.value == price);

        if (_referrerWalletAddress != address(0) && _referrerWalletAddress != msg.sender && price > 0) {
            referrerPrize = SafeMath.div(price, 10);
            if (referrerPrize < price) {
                eternalStorageContract.addReferrer(_referrerWalletAddress, referrerPrize);
            }
        }

        _buyShip(_shipId, msg.sender);
	}

    function _buyShip(uint256 _shipId, address _newOwner) private {
        uint256 myShipId = eternalStorageContract.buyItem(_shipId, _newOwner, "ship", "ship_types", "ship_ids");
        emit ShipWasBought(myShipId);
    }

    function withdrawRefund() external addressIsNotNull(msg.sender) {
        uint256 curRefVal = eternalStorageContract.checkRefundExistanceByOwner(msg.sender);
        if (curRefVal > 0 && address(this).balance > curRefVal && SafeMath.sub(address(this).balance, curRefVal) > 0) {
            uint256 refund = eternalStorageContract.widthdrawRefunds(msg.sender);
            msg.sender.transfer(refund);
        }
    }

    function checkRefundExistanceByOwner() external addressIsNotNull(msg.sender) view returns(uint256) {
        return eternalStorageContract.checkRefundExistanceByOwner(msg.sender);
    }

    /* ------ READING METHODS FOR USERS ITEMS ------ */

    function getNumberOfShipsByOwner() public view returns(uint256) {
        return eternalStorageContract.getNumberOfItemsByTypeAndOwner("ship", msg.sender);
    }

    function getShipsByOwner() public view returns(uint256[]) {
        return eternalStorageContract.getItemsByTypeAndOwner("ship_types", msg.sender);
    }
    
    function getShipIdsByOwner() public view returns(uint256[]) {
        return eternalStorageContract.getItemsIdsByTypeAndOwner("ship_ids", msg.sender);
    }

    function getOwnerByShipId(uint256 _shipId) public view returns(address) {
        return eternalStorageContract.getOwnerByItemTypeAndId("ship", _shipId);
    }

    /* ------ READING METHODS FOR ALL USERS ITEMS ------ */

    // Ships
    function getUsersShipsIds() public view returns(uint256[]) {
        return itemsStorageContract.getUsersShipsIds();
    }

    /* ------ READING METHODS FOR ALL ITEMS ------ */

    // Get item price
    function getShipPriceById(uint256 _shipId) public view returns(uint256) {
        return eternalStorageContract.getItemPriceById("ships", _shipId);
    }

    // Ships
    function getShipsIds() public view returns(uint256[]) {
        return itemsStorageContract.getShipsIds();
    }

    function getShipById(uint256 _shipId) public view returns(
        uint256,
        string,
        uint256,
        uint256,
        uint256
    ) {
        return eternalStorageContract.getShipById(_shipId);
    }

    /* ------ DEV FUNCTIONS ------ */

    function getBalanceOfLogicContract() public onlyOwner view returns(uint256) {
        return address(this).balance;
    }

    function getPayOut() public onlyOwner returns(uint256) {
		_getPayOut();
	}

	function _getPayOut() private returns(uint256){
		if (msg.sender != address(0)) {
			msg.sender.transfer(address(this).balance);
            return address(this).balance;
		}
	}

    function setNewPriceToItem(string _itemType, uint256 _itemTypeId, uint256 _newPrice) public onlyOwner {
        eternalStorageContract.setNewPriceToItem(_itemType, _itemTypeId, _newPrice);
    }
}
function getBalanceOfLogicContract() public onlyOwner view returns(uint256) {
    return address(this).balance;
}

/* ------ DEV FUNCTIONS ------ */