contract AlpacaWearable is ERC1155(""), Ownable, IAlpacaWearable {
    using EnumerableSet for EnumerableSet.AddressSet;

    /* ========== EVENT ========== */

    event AddWearable(uint256 indexed wearableId, uint256 energy);

    event UpdateWearableEnergy(
        uint256 indexed wearableId,
        uint256 prevEnergy,
        uint256 newEnergy
    );

    /* ========== STORAGE ========== */

    struct Wearable {
        uint32 energy;
        uint32 wearableType;
    }

    Wearable[] public wearables;

    // Set of alpaca IDs this contract owns
    EnumerableSet.AddressSet private minters;

    constructor() public {
        minters.add(msg.sender);
        wearables.push(Wearable({energy: 0, wearableType: 0}));
    }

    /* ========== VIEW ========== */

    function wearableCount() public view returns (uint256) {
        return wearables.length;
    }

    function getWearable(uint256 _id)
        external
        override
        view
        returns (
            uint256 id,
            uint256 energy,
            uint256 wearableType
        )
    {
        require(id < wearables.length);

        Wearable storage wearable = wearables[_id];
        id = _id;
        energy = wearable.energy;
        wearableType = wearable.wearableType;
    }

    /* ========== MUTATION ========== */

    function addWearable(uint32 energy, uint32 wearableType)
        public
        onlyOwner
        returns (uint256)
    {
        require(wearableType != 0, "invalid type");

        uint256 id = wearables.length;
        wearables.push(Wearable({energy: energy, wearableType: wearableType}));
        emit AddWearable(id, energy);
        return id;
    }

    function updateWearableEnergy(uint256 index, uint32 energy)
        public
        onlyOwner
    {
        require(index < wearables.length);

        Wearable storage wearable = wearables[index];
        uint256 prevEnergy = wearable.energy;
        wearable.energy = energy;

        emit UpdateWearableEnergy(index, prevEnergy, energy);
    }

    function mint(
        address account,
        uint256 id,
        uint256 amount,
        bytes memory data
    ) public override onlyMinter {
        require(id < wearables.length);
        _mint(account, id, amount, data);
    }

    function mintBatch(
        address to,
        uint256[] memory ids,
        uint256[] memory amounts,
        bytes memory data
    ) public override onlyMinter {
        for (uint256 i = 0; i < ids.length; i++) {
            require(ids[i] < wearables.length);
        }
        _mintBatch(to, ids, amounts, data);
    }

    function burn(
        address account,
        uint256 id,
        uint256 amount
    ) public override onlyMinter {
        _burn(account, id, amount);
    }

    function burnBatch(
        address account,
        uint256[] memory ids,
        uint256[] memory amounts
    ) public override onlyMinter {
        _burnBatch(account, ids, amounts);
    }

    function setURI(string memory _uri) public onlyOwner {
        _setURI(_uri);
    }

    function addMinter(address _minter) public onlyOwner {
        minters.add(_minter);
    }

    function removeMinter(address _minter) public onlyOwner {
        minters.remove(_minter);
    }

    function isMinter(address _minter) public view returns (bool) {
        minters.contains(_minter);
    }

    modifier onlyMinter() {
        require(
            minters.contains(_msgSender()),
            "AlpacaWearable: caller is not the minter"
        );
        _;
    }
}
// import "@openzeppelin/contracts/token/ERC1155/ERC1155.sol";
// import "@openzeppelin/contracts/access/Ownable.sol";
// import "@openzeppelin/contracts/utils/EnumerableSet.sol";
// import "contracts/interfaces/IAlpacaWearable.sol";
function wearableCount() public view returns (uint256) {
    return wearables.length;
}

/* ========== VIEW ========== */