contract PixelChainCore is Ownable, ERC721Full {
    event PixelChainCreated(uint id, address author, string name, bytes data, bytes palette);

    string public name = "PixelChain";
    string public symbol = "PXC";
    string baseTokenUri = "";
    uint256 mintPrice = 0;

    struct PixelChain {
        string name;
        bytes data;
        bytes palette;
        address author;
        uint256 date;
    }

    PixelChain[] public pixelChains;

    constructor() ERC721Full(name, symbol) public { }

    function tokenURI(uint256 _tokenId) external view returns (string memory) {
        return Strings.strConcat(
            baseTokenURI(),
            Strings.uint2str(_tokenId)
        );
    }

    // Management methods
    function create(string memory _name, bytes memory _data, bytes memory _palette) public payable returns (uint) {
        require(msg.value >= mintPrice, "Not enough ether to mint this token!");
        require(_data.length == 1024, "The byte array length should be of 1024.");
        require(_palette.length == 48, "The palette array length should be of 48.");

        if (msg.value > mintPrice) {
            msg.sender.transfer(msg.value - mintPrice);
        }

        uint id = pixelChains.push(PixelChain(_name, _data, _palette, msg.sender, block.timestamp)) - 1;
        _mint(msg.sender, id);
        emit PixelChainCreated(id, msg.sender, _name, _data, _palette);
        return id;
    }

    function retrieve(uint256 _id) public view  returns (string memory, bytes memory, bytes memory, address, uint256) {
        return (pixelChains[_id].name, pixelChains[_id].data, pixelChains[_id].palette, pixelChains[_id].author, pixelChains[_id].date);
    }

    function setBaseTokenURI(string memory _uri) public onlyOwner {
        baseTokenUri = _uri;
    }

    function withdraw() external onlyOwner {
        msg.sender.transfer(address(this).balance);
    }

    function setMintPrice(uint256 _price) external onlyOwner {
        mintPrice = _price;
    }

    function baseTokenURI() public view returns (string memory) {
        return baseTokenUri;
    }

}
function create(string memory _name, bytes memory _data, bytes memory _palette) public payable returns (uint) {
    require(msg.value >= mintPrice, "Not enough ether to mint this token!");
    require(_data.length == 1024, "The byte array length should be of 1024.");
    require(_palette.length == 48, "The palette array length should be of 48.");

    if (msg.value > mintPrice) {
        msg.sender.transfer(msg.value - mintPrice);
    }

    uint id = pixelChains.push(PixelChain(_name, _data, _palette, msg.sender, block.timestamp)) - 1;
    _mint(msg.sender, id);
    emit PixelChainCreated(id, msg.sender, _name, _data, _palette);
    return id;
}

// Management methods