// SPDX-License-Identifier: SEE LICENSE IN LICENSE
pragma solidity ^0.8.12;

import "@openzeppelin/contracts/utils/Strings.sol";
import "@openzeppelin/contracts/utils/structs/EnumerableSet.sol";
import "@openzeppelin/contracts/utils/math/SafeMath.sol";

error MergeCanvas_AlreadyMerged(string reason);
error MergeCanvas_NotOwner(address sender);
error MergeCanvas_XCoordinateOutOfBounds(uint16 x, uint16 max_value);
error MergeCanvas_YCoordinateOutOfBounds(uint16 y, uint16 max_value);
error MergeCanvas_InvalidRGBColor(uint16 invalid_num);
error MergeCanvas_InsufficientBid(uint256 bid, uint256 curr_price);
error MergeCanvas_FailedBidRefund();
error MergeCanvas_NotContributor(address sender);
error MergeCanvas_AddressAtMaxPixelCapacity(address sender);

interface IMergeCanvas {
    struct RGB {
        uint8 R;
        uint8 G;
        uint8 B;
    }

    event PixelChange(
        uint16 x,
        uint16 y,
        RGB new_color,
        address indexed new_owner,
        uint256 new_price
    );

    event PixelChangeFail(
        uint16 x,
        uint16 y,
        RGB new_color,
        address indexed old_owner,
        address indexed new_owner
    );

    function hasContributed(address _address) external view returns (bool);

    function changePixelColor(
        uint16 _x,
        uint16 _y,
        RGB calldata _new_color
    )
    external
    payable;

    //
    // @dev Change color of multiple pixels
    //
    function changePixelsColor(
        uint16[] memory _x,
        uint16[] memory _y,
        RGB[] calldata _new_color,
        uint256[] memory _prices
    )
    external
    payable;

    function getPixelOwner(uint16 _x, uint16 _y)
    external
    view
    returns (address owner);

    function getPixelColor(uint16 _x, uint16 _y)
    external
    view
    returns (RGB memory color);

    function getPixelPrice(uint16 _x, uint16 _y)
    external
    view
    returns (uint256 pixel_price);

    // Could remove function and instead use getPixelsForAddress()
    function getAddressPixels(address _address)
    external
    view
    returns (uint256[] memory address_pixels);

    function numberOfPixels(address _address) external view returns (uint256);

    function mergeNow() external;

    function withdraw() external;

    function mergeStatus() external view returns (bool);

    function setBatchAllowed(bool _allow) external;
}
[{"inputs":[{"internalType":"uint16","name":"_canvas_dimension","type":"uint16"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"sender","type":"address"}],"name":"MergeCanvas_AddressAtMaxPixelCapacity","type":"error"},{"inputs":[{"internalType":"string","name":"reason","type":"string"}],"name":"MergeCanvas_AlreadyMerged","type":"error"},{"inputs":[],"name":"MergeCanvas_FailedBidRefund","type":"error"},{"inputs":[{"internalType":"uint256","name":"bid","type":"uint256"},{"internalType":"uint256","name":"curr_price","type":"uint256"}],"name":"MergeCanvas_InsufficientBid","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"}],"name":"MergeCanvas_NotContributor","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"}],"name":"MergeCanvas_NotOwner","type":"error"},{"inputs":[{"internalType":"uint16","name":"x","type":"uint16"},{"internalType":"uint16","name":"max_value","type":"uint16"}],"name":"MergeCanvas_XCoordinateOutOfBounds","type":"error"},{"inputs":[{"internalType":"uint16","name":"y","type":"uint16"},{"internalType":"uint16","name":"max_value","type":"uint16"}],"name":"MergeCanvas_YCoordinateOutOfBounds","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint16","name":"x","type":"uint16"},{"indexed":false,"internalType":"uint16","name":"y","type":"uint16"},{"components":[{"internalType":"uint8","name":"R","type":"uint8"},{"internalType":"uint8","name":"G","type":"uint8"},{"internalType":"uint8","name":"B","type":"uint8"}],"indexed":false,"internalType":"struct IMergeCanvas.RGB","name":"new_color","type":"tuple"},{"indexed":true,"internalType":"address","name":"new_owner","type":"address"},{"indexed":false,"internalType":"uint256","name":"new_price","type":"uint256"}],"name":"PixelChange","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint16","name":"x","type":"uint16"},{"indexed":false,"internalType":"uint16","name":"y","type":"uint16"},{"components":[{"internalType":"uint8","name":"R","type":"uint8"},{"internalType":"uint8","name":"G","type":"uint8"},{"internalType":"uint8","name":"B","type":"uint8"}],"indexed":false,"internalType":"struct IMergeCanvas.RGB","name":"new_color","type":"tuple"},{"indexed":true,"internalType":"address","name":"old_owner","type":"address"},{"indexed":true,"internalType":"address","name":"new_owner","type":"address"}],"name":"PixelChangeFail","type":"event"},{"inputs":[],"name":"CANVAS_DIMENSION","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"_x","type":"uint16"},{"internalType":"uint16","name":"_y","type":"uint16"},{"components":[{"internalType":"uint8","name":"R","type":"uint8"},{"internalType":"uint8","name":"G","type":"uint8"},{"internalType":"uint8","name":"B","type":"uint8"}],"internalType":"struct IMergeCanvas.RGB","name":"_new_color","type":"tuple"}],"name":"changePixelColor","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint16[]","name":"_x","type":"uint16[]"},{"internalType":"uint16[]","name":"_y","type":"uint16[]"},{"components":[{"internalType":"uint8","name":"R","type":"uint8"},{"internalType":"uint8","name":"G","type":"uint8"},{"internalType":"uint8","name":"B","type":"uint8"}],"internalType":"struct IMergeCanvas.RGB[]","name":"_new_color","type":"tuple[]"},{"internalType":"uint256[]","name":"_prices","type":"uint256[]"}],"name":"changePixelsColor","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"_address","type":"address"}],"name":"getAddressPixels","outputs":[{"internalType":"uint256[]","name":"address_pixels","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"_x","type":"uint16"},{"internalType":"uint16","name":"_y","type":"uint16"}],"name":"getPixelColor","outputs":[{"components":[{"internalType":"uint8","name":"R","type":"uint8"},{"internalType":"uint8","name":"G","type":"uint8"},{"internalType":"uint8","name":"B","type":"uint8"}],"internalType":"struct IMergeCanvas.RGB","name":"color","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"_x","type":"uint16"},{"internalType":"uint16","name":"_y","type":"uint16"}],"name":"getPixelOwner","outputs":[{"internalType":"address","name":"owner","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"_x","type":"uint16"},{"internalType":"uint16","name":"_y","type":"uint16"}],"name":"getPixelPrice","outputs":[{"internalType":"uint256","name":"pixel_price","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_address","type":"address"}],"name":"hasContributed","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"mergeNow","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"mergeStatus","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_address","type":"address"}],"name":"numberOfPixels","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bool","name":"_allow","type":"bool"}],"name":"setBatchAllowed","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"}]