// SPDX-License-Identifier: MIT

pragma solidity 0.8.4;

import "@openzeppelin/contracts/access/Ownable.sol";
import "../RFOXNFTWhitelist.sol";
import "../structs/ParamStructs.sol";

contract RFOXFactoryWhitelist is Ownable {
    address[] public allNFTs;

    event NewRFOXNFT(address indexed nftAddress, ParamStructs.WhitelistParams params);

    function createNFT(ParamStructs.WhitelistParams calldata _params) external onlyOwner returns (address newNFT) {
        ParamStructs.WhitelistParams memory params = _params;
        bytes memory bytecode = type(RFOXNFTWhitelist).creationCode;
        bytes32 salt = keccak256(
            abi.encodePacked(allNFTs.length, params.name, params.symbol)
        );

        assembly {
            newNFT := create2(0, add(bytecode, 32), mload(bytecode), salt)
        }

        RFOXNFTWhitelist(newNFT).initialize(params);

        allNFTs.push(address(newNFT));

        emit NewRFOXNFT(newNFT, params);

        return address(newNFT);
    }
}
[{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"nftAddress","type":"address"},{"components":[{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"symbol","type":"string"},{"internalType":"string","name":"baseURI","type":"string"},{"internalType":"contract IERC20","name":"saleToken","type":"address"},{"internalType":"uint256","name":"price","type":"uint256"},{"internalType":"uint256","name":"maxNft","type":"uint256"},{"internalType":"uint256","name":"maxTokensPerTransaction","type":"uint256"},{"internalType":"uint256","name":"saleStartTime","type":"uint256"},{"internalType":"uint256","name":"saleEndTime","type":"uint256"},{"internalType":"uint256","name":"publicSaleStartTime","type":"uint256"},{"internalType":"uint256","name":"maxMintedPresalePerAddress","type":"uint256"},{"internalType":"uint256","name":"pricePresale","type":"uint256"},{"internalType":"address","name":"owner","type":"address"}],"indexed":false,"internalType":"struct ParamStructs.WhitelistParams","name":"params","type":"tuple"}],"name":"NewRFOXNFT","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"allNFTs","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"symbol","type":"string"},{"internalType":"string","name":"baseURI","type":"string"},{"internalType":"contract IERC20","name":"saleToken","type":"address"},{"internalType":"uint256","name":"price","type":"uint256"},{"internalType":"uint256","name":"maxNft","type":"uint256"},{"internalType":"uint256","name":"maxTokensPerTransaction","type":"uint256"},{"internalType":"uint256","name":"saleStartTime","type":"uint256"},{"internalType":"uint256","name":"saleEndTime","type":"uint256"},{"internalType":"uint256","name":"publicSaleStartTime","type":"uint256"},{"internalType":"uint256","name":"maxMintedPresalePerAddress","type":"uint256"},{"internalType":"uint256","name":"pricePresale","type":"uint256"},{"internalType":"address","name":"owner","type":"address"}],"internalType":"struct ParamStructs.WhitelistParams","name":"_params","type":"tuple"}],"name":"createNFT","outputs":[{"internalType":"address","name":"newNFT","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"}]