contract NftConvoy is ERC1155, Ownable, Pausable {
    uint private constant MAX_SUPPLY = 10000;
    uint private constant MAX_PER_TX = 100;
    
    // Meta
    uint private counter;
    string public name = "NftConvoy";

    // Price
    uint256 public price;
    address payable public receiver;

    constructor (
        string memory _tokenURI,
        address payable _receiver,
        uint _mintingFee
    ) ERC1155(_tokenURI) {
        receiver = _receiver;
        price = _mintingFee;
        counter = 0;
        _pause();
    }

    function setPause(bool pause) external onlyOwner {
        if(pause) {
            _pause();
        } else {
            _unpause();
        }
    }

    function totalSupply() external view returns (uint) {
        return counter;
    }

    function mint(uint amount) external payable whenNotPaused {
        require(amount < MAX_PER_TX + 1, "amount can't exceed 100");
        require(amount > 0, "not enough sent");
        require(msg.value == price * amount, "insufficient funds");
        require(counter + amount < MAX_SUPPLY, "none left");

        mintBatch(msg.sender, amount);
    }

    function mintBatch(address to, uint amount) private {
        uint256[] memory ids = new uint256[](amount);
        uint256[] memory amounts = new uint256[](amount);
        uint c = 0;
        for(uint i = counter; i < counter + amount; i++) {
            ids[c] = i+1; // token starts at 1
            amounts[c] = 1;
            c++;
        }
        counter += amount;
        _mintBatch(to, ids, amounts, "");
    }

    function airdrop(address[] calldata target, uint[] calldata amount) external onlyOwner {
        require(target.length > 0, "no target");
        require(amount.length > 0, "no amount");
        require(target.length == amount.length, "amount and target mismatch");
        uint totalAmount = 0;
        for(uint i; i < amount.length; i++){
            totalAmount += amount[i];
        }
        require(counter + totalAmount < MAX_SUPPLY, "no more left to mint");
        for(uint i; i < target.length; i++) {
            mintBatch(target[i], amount[i]);
        }
    }

    // Mint
    function setPrice(uint amount) external onlyOwner {
        price = amount;
    }
    function setReceiver(address payable _receiver) external onlyOwner {
        receiver = _receiver;
    }
    function claim() external {
        require(receiver == msg.sender, "invalid receiver");
        receiver.transfer(address(this).balance);
    }

    // Meta
    function setTokenURI(string calldata _uri) external onlyOwner {
        _setURI(_uri);
    }
    function uri(uint256 _tokenId) public view virtual override returns (string memory) {
        return string(abi.encodePacked(
            super.uri(_tokenId),
            "/",
            Strings.toString(_tokenId),
            ".json"
        ));
    }
}
function setPrice(uint amount) external onlyOwner {
    price = amount;
}

// Mint