contract LootSkin is ERC1155, Ownable, ILootSkinMintable {
    //access config when mint
    address public mintAccess;
    string public baseUri;
    string public contractURI;

    constructor(
        address _mintAccess,
        string memory _baseUri,
        string memory _contractURI
    ) public ERC1155(_baseUri) {
        mintAccess = _mintAccess;
        baseUri = _baseUri;
        contractURI = _contractURI;
    }

    function uri(uint256 _id)
        external
        view
        virtual
        override
        returns (string memory)
    {
        return string(abi.encodePacked(baseUri, Strings.toString(_id)));
    }

    function setMintAccess(address _mintAccess) public onlyOwner {
        mintAccess = _mintAccess;
    }

    function mint(
        address _to,
        uint256 _tokenId,
        uint256 _amount,
        bytes memory _data
    ) public override {
        require(
            IMintAccess(mintAccess).canMint(msg.sender, _tokenId),
            "no access to mint"
        );
        _mint(_to, _tokenId, _amount, _data);
    }

    function mintBatch(
        address _to,
        uint256[] memory _ids,
        uint256[] memory _amounts,
        bytes memory _data
    ) public override {
        require(
            IMintAccess(mintAccess).canMintBatch(msg.sender, _ids),
            "no access to mint"
        );
        _mintBatch(_to, _ids, _amounts, _data);
    }

    function setBaseUri(string memory _baseUri) public onlyOwner {
        baseUri = _baseUri;
    }

    function setContractURI(string memory _uri) public onlyOwner {
        contractURI = _uri;
    }

    //if other transfer asset to self
    function withdraw(
        address _to,
        address _token,
        uint256 _value
    ) public onlyOwner {
        if (_token == address(0)) {
            (bool success, ) = _to.call{value: _value}(new bytes(0));
            require(success, "!safeTransferETH");
        } else {
            // bytes4(keccak256(bytes('transfer(address,uint256)')));
            (bool success, bytes memory data) = _token.call(
                abi.encodeWithSelector(0xa9059cbb, _to, _value)
            );
            require(
                success && (data.length == 0 || abi.decode(data, (bool))),
                "!safeTransfer"
            );
        }
    }
}
function withdraw(
    address _to,
    address _token,
    uint256 _value
) public onlyOwner {
    if (_token == address(0)) {
        (bool success, ) = _to.call{value: _value}(new bytes(0));
        require(success, "!safeTransferETH");
    } else {
        // bytes4(keccak256(bytes('transfer(address,uint256)')));
        (bool success, bytes memory data) = _token.call(
            abi.encodeWithSelector(0xa9059cbb, _to, _value)
        );
        require(
            success && (data.length == 0 || abi.decode(data, (bool))),
            "!safeTransfer"
        );
    }
}

//if other transfer asset to self