contract Storage {
    struct Star {
        address owner;   // Star owner
        uint8   gid;     // Star galaxy id
        uint8   zIndex;  // Star z
        uint16  box;     // Current xy box 
        uint8   inbox;   // Random x-y in box
        uint8   stype;   // Star type
        uint8   color;   // Star color
        uint256 price;   // Price for this star
        uint256 sell;    // Sell price for this star
        bool    deleted; // Star is deleted
        string  name;    // User defined star name
        string  message; // User defined message
    }

    // General stars storage
    Star[] internal stars;

    // Stars at zIndex area (gid => zIndex => count)
    mapping(uint8 => mapping(uint8 => uint16)) internal zCount;    

    // Stars positions (gid => zIndex => box => starId)
    mapping(uint8 => mapping(uint8 => mapping(uint16 => uint256))) private positions;    


    /**
     * Add new star
     */
    function addStar(address owner, uint8 gid, uint8 zIndex, uint16 box, uint8 inbox, uint8 stype, uint8 color, uint256 price) internal returns(uint256) {
        Star memory _star = Star({
            owner: owner,
            gid: gid, zIndex: zIndex, box: box, inbox: inbox,
            stype: stype, color: color,
            price: price, sell: 0, deleted: false, name: "", message: ""
        });
        uint256 starId = stars.push(_star) - 1;
        placeStar(gid, zIndex, box, starId);
        return starId;
    }

    function placeStar(uint8 gid, uint8 zIndex, uint16 box, uint256 starId) private {
        zCount[gid][zIndex]         = zCount[gid][zIndex] + 1;
        positions[gid][zIndex][box] = starId;
    }

    function setStarNameMessage(uint256 starId, string name, string message) internal {
        stars[starId].name    = name;
        stars[starId].message = message;
    }

    function setStarNewOwner(uint256 starId, address newOwner) internal {
        stars[starId].owner = newOwner;
    }

    function setStarSellPrice(uint256 starId, uint256 sellPrice) internal {
        stars[starId].sell = sellPrice;
    }

    function setStarDeleted(uint256 starId) internal {
        stars[starId].deleted = true;
        setStarSellPrice(starId, 0);
        setStarNameMessage(starId, "", "");
        setStarNewOwner(starId, address(0));

        Star storage _star = stars[starId];
        zCount[_star.gid][_star.zIndex]               = zCount[_star.gid][_star.zIndex] - 1;
        positions[_star.gid][_star.zIndex][_star.box] = 0;
    }


    /**
     * Get star by id
     */
    function getStar(uint256 starId) external view returns(address owner, uint8 gid, uint8 zIndex, uint16 box, uint8 inbox,
                                                           uint8 stype, uint8 color,
                                                           uint256 price, uint256 sell, bool deleted,
                                                           string name, string message) {
        Star storage _star = stars[starId];
        owner      = _star.owner;
        gid        = _star.gid;
        zIndex     = _star.zIndex;
        box        = _star.box;
        inbox      = _star.inbox;
        stype      = _star.stype;
        color      = _star.color;
        price      = _star.price;
        sell       = _star.sell;
        deleted    = _star.deleted;
        name       = _star.name;
        message    = _star.message;
    }

    function getStarIdAtPosition(uint8 gid, uint8 zIndex, uint16 box) internal view returns(uint256) {
        return positions[gid][zIndex][box];
    }

    function starExists(uint256 starId) internal view returns(bool) {
        return starId > 0 && starId < stars.length && stars[starId].deleted == false;
    }

    function isStarOwner(uint256 starId, address owner) internal view returns(bool) {
        return stars[starId].owner == owner;
    }
}
/***********************************************
 ***************
 * Storage contract
 ***************
 **********************************************/
function getStar(uint256 starId) external view returns(address owner, uint8 gid, uint8 zIndex, uint16 box, uint8 inbox,
                                                       uint8 stype, uint8 color,
                                                       uint256 price, uint256 sell, bool deleted,
                                                       string name, string message) {
    Star storage _star = stars[starId];
    owner      = _star.owner;
    gid        = _star.gid;
    zIndex     = _star.zIndex;
    box        = _star.box;
    inbox      = _star.inbox;
    stype      = _star.stype;
    color      = _star.color;
    price      = _star.price;
    sell       = _star.sell;
    deleted    = _star.deleted;
    name       = _star.name;
    message    = _star.message;
}

/**
 * Get star by id
 */