contract CryptoodleToken is Context, Ownable, ERC20 {
    address public lootContractAddress =
        0xFF9C1b15B16263C61d017ee9F65C50e4AE0113D7;
    IERC721Enumerable public lootContract;

    address public toodleLootContractAddress =
        0x2A16107Ea0D28aE822168C8bB3eF5460b1924A78;
    IERC721Enumerable public toodleContract;

    address public moreLootContractAddress =
        0x1dfe7Ca09e99d10835Bf73044a23B73Fc20623DF;
    IERC721Enumerable public moreLootContract;

    bool public airdropForOGLootActive = true;
    bool public airdropForToodleLootActive = true;
    bool public airdropForMoreLootActive = true;

    // Airdrop 15 MIL TODL to each Toodle Loot Bag
    uint256 private todlForToodleLoot = 15000000 * (10**decimals());

    // Airdrop 5 MIL TODL to each Loot
    uint256 private todlForOgLoot = 5000000 * (10**decimals());

    // Airdrop 100K TODL to each More Loot Bag
    uint256 private todlForMoreLoot = 100000 * (10**decimals());

    uint256 private tokenIdStart = 1;
    uint256 private tokenIdStartMoreLoot = 8001;

    uint256 private tokenIdEnd = 8000;
    uint256 public tokenIdEndMoreLoot = 1316004;
    uint256 private tokenIdEndToodleLoot = 10000;

    // Track claimed airdropped tokens for each Loot bag
    mapping(uint256 => bool) public ogLootClaimedByTokenId;
    mapping(uint256 => bool) public toodleLootClaimedByTokenId;
    mapping(uint256 => bool) public moreLootClaimedByTokenId;

    constructor() Ownable() ERC20("Cryptoodles Toodle Token", "TODL") {
        lootContract = IERC721Enumerable(lootContractAddress);
        toodleContract = IERC721Enumerable(toodleLootContractAddress);
        moreLootContract = IERC721Enumerable(moreLootContractAddress);
    }

    function claimByToodleLootIds(uint256[] memory tokenId) external {
        require(airdropForToodleLootActive, "Air drop for Toodle Loot Bag is not active");

        for(uint256 i = 0; i < tokenId.length; i++){
        
        require(
            _msgSender() == toodleContract.ownerOf(tokenId[i]),
            "Error: A Loot Bag is not in your wallet"
        );

        _claim(tokenId[i], _msgSender(), 1);
        }
    }

    function claimByOGLootIds(uint256[] memory tokenId) external {
        require(airdropForOGLootActive, "Air drop for OG Loot Bag is not active");

        for(uint256 i = 0; i < tokenId.length; i++){
        
        require(
            _msgSender() == lootContract.ownerOf(tokenId[i]),
            "Error: A Loot Bag is not in your wallet"
        );

        _claim(tokenId[i], _msgSender(), 0);
        }
    }

    function claimByMoreLootIds(uint256[] memory tokenId) external {
        require(airdropForMoreLootActive, "Air drop for More Loot Bag is not active");

        for(uint256 i = 0; i < tokenId.length; i++){
        
        require(
            _msgSender() == moreLootContract.ownerOf(tokenId[i]),
            "Error: A Loot Bag is not in your wallet"
        );

        _claim(tokenId[i], _msgSender(), 2);
        }
    }

    // Deflationary mechanism to burn TODL from the caller's address and decrease overall supply
    function burn(uint256 amount) external {
        _burn(_msgSender(), amount * (10**decimals()));
    }

    function _claim(uint256 tokenId, address tokenOwner, uint256 contractId) internal {

        // Logic to claim aidropped tokens from OG Loot Bag
        if(contractId == 0) {
        require(
            tokenId >= tokenIdStart && tokenId <= tokenIdEnd,
            "Error: Invalid tokenId"
        );
        require(
            !ogLootClaimedByTokenId[tokenId],
            "Error: You included a Loot Bag with TODL already claimed for the airdrop"
        );
        
        ogLootClaimedByTokenId[tokenId] = true;
        _mint(tokenOwner, todlForOgLoot);

        }
        // Logic to claim aidropped tokens from Toodle Loot Bag
        else if (contractId == 1) {
        require(
            tokenId >= tokenIdStart && tokenId <= tokenIdEndToodleLoot,
            "Error: Invalid tokenId"
        );
        require(
            !toodleLootClaimedByTokenId[tokenId],
            "Error: You included a Loot Bag with TODL already claimed for the airdrop"
        );
        
        toodleLootClaimedByTokenId[tokenId] = true;
        _mint(tokenOwner, todlForToodleLoot);
        }
        // Logic to claim aidropped tokens from More Loot Bag 
        else if (contractId == 2) {
        require(
            tokenId >= tokenIdStartMoreLoot && tokenId <= tokenIdEndMoreLoot,
            "Error: Invalid tokenId"
        );
        require(
            !moreLootClaimedByTokenId[tokenId],
            "Error: You included a Loot Bag with TODL already claimed for the airdrop"
        );

        moreLootClaimedByTokenId[tokenId] = true;
        _mint(tokenOwner,todlForMoreLoot);
        }
    }

    // Inflationary mechanism to increase supply
    function mint(uint256 amountDisplayValue) external onlyOwner {
        _mint(owner(), amountDisplayValue * (10**decimals()));
    }

    // Pauses or resumes the TODL airdrop for Loot Bags. Used instead of burning TODL from each bag of the air drop for gas savings
    function pauseAirdrop(bool value, uint256 contractId) external onlyOwner {
        if(contractId == 0){
            airdropForOGLootActive = value;
        } else if(contractId == 1){
            airdropForToodleLootActive = value;
        } else if(contractId == 2){
            airdropForMoreLootActive = value;
        }
    }

    // Used in case More Loot bag max estimation is different than the one initialized in the contract
    function setMoreLootEndTokenId(uint256 tokenId) external onlyOwner {
        tokenIdEndMoreLoot = tokenId;
    }

    function setLootContractAddress(address lootContractAddress_)
        external
        onlyOwner
    {
        lootContractAddress = lootContractAddress_;
        lootContract = IERC721Enumerable(lootContractAddress);
    }

    function setToodleLootContractAddress(address lootContractAddress_)
        external
        onlyOwner
    {
        toodleLootContractAddress = lootContractAddress_;
        toodleContract = IERC721Enumerable(toodleLootContractAddress);
    }

    function setMoreLootContractAddress(address lootContractAddress_)
        external
        onlyOwner
    {
        moreLootContractAddress = lootContractAddress_;
        moreLootContract = IERC721Enumerable(moreLootContractAddress);
    }
}
// Cryptoodles TODL Token 
// An airdrop contract for Loot Bag, More Loot, and Toodle Loot Bag holders to claim Cryptoodles native token
// https://cryptoodles.com
// This contract has not been officially audited. Use at your own risk.
function setMoreLootEndTokenId(uint256 tokenId) external onlyOwner {
    tokenIdEndMoreLoot = tokenId;
}

// Used in case More Loot bag max estimation is different than the one initialized in the contract