contract ArtworkMinting is ArtworkAuction {

    // Limits the number of arts the contract owner can ever create.
    uint256 public constant PROMO_CREATION_LIMIT = 5000;
    uint256 public constant CREATION_LIMIT = 450000;

    // Constants for auctions.
    uint256 public constant ARTWORK_STARTING_PRICE = 10 finney;
    uint256 public constant ARTWORK_AUCTION_DURATION = 1 days;

    // Counts the number of arts the contract owner has created.
    uint256 public promoCreatedCount;
    uint256 public artsCreatedCount;

    /// @dev we can create promo artworks, up to a limit. Only callable by COO
    /// @param _owner the future owner of the created artworks. Default to contract COO
    function createPromoArtwork(string _name, string _author, uint32 _series, address _owner) external onlyCOO {
        bytes32 uniqueKey = getUniqueKey(_name, _author, _series);
        (require(!uniqueArtworks[uniqueKey]));
        if (_series != 0) {
            bytes32 uniqueKeyForZero = getUniqueKey(_name, _author, 0);
            (require(!uniqueArtworks[uniqueKeyForZero]));
        }
        address artworkOwner = _owner;
        if (artworkOwner == address(0)) {
            artworkOwner = cooAddress;
        }
        require(promoCreatedCount < PROMO_CREATION_LIMIT);

        promoCreatedCount++;
        _createArtwork(_name, _author, _series, artworkOwner);
        uniqueArtworks[uniqueKey] = true;
    }

    /// @dev Creates a new artwork with the given name and author and
    ///  creates an auction for it.
    function createArtworkAuction(string _name, string _author, uint32 _series) external onlyCOO {
        bytes32 uniqueKey = getUniqueKey(_name, _author, _series);
        (require(!uniqueArtworks[uniqueKey]));
        require(artsCreatedCount < CREATION_LIMIT);
        if (_series != 0) {
            bytes32 uniqueKeyForZero = getUniqueKey(_name, _author, 0);
            (require(!uniqueArtworks[uniqueKeyForZero]));
        }
        uint256 artworkId = _createArtwork(_name, _author, _series, address(this));
        _approve(artworkId, saleAuction);
        uint256 price = _computeNextArtworkPrice();
        saleAuction.createAuction(
            artworkId,
            price,
            0,
            ARTWORK_AUCTION_DURATION,
            address(this)
        );
        artsCreatedCount++;
        uniqueArtworks[uniqueKey] = true;
    }

    /// @dev Computes the next gen0 auction starting price, given
    ///  the average of the past 5 prices + 50%.
    function _computeNextArtworkPrice() internal view returns (uint256) {
        uint256 avePrice = saleAuction.averageArtworkSalePrice();

        // Sanity check to ensure we don't overflow arithmetic
        require(avePrice == uint256(uint128(avePrice)));

        uint256 nextPrice = avePrice + (avePrice / 2);

        // We never auction for less than starting price
        if (nextPrice < ARTWORK_STARTING_PRICE) {
            nextPrice = ARTWORK_STARTING_PRICE;
        }

        return nextPrice;
    }
}
/// @title all functions related to creating artworks
function _computeNextArtworkPrice() internal view returns (uint256) {
    uint256 avePrice = saleAuction.averageArtworkSalePrice();

    // Sanity check to ensure we don't overflow arithmetic
    require(avePrice == uint256(uint128(avePrice)));

    uint256 nextPrice = avePrice + (avePrice / 2);

    // We never auction for less than starting price
    if (nextPrice < ARTWORK_STARTING_PRICE) {
        nextPrice = ARTWORK_STARTING_PRICE;
    }

    return nextPrice;
}

/// @dev Computes the next gen0 auction starting price, given
///  the average of the past 5 prices + 50%.