contract ShiryoinuPack is IShiryoinuPack,ERC721Enumerable, Ownable{
    using SafeMath for uint256;
    using Counters for Counters.Counter;

    modifier onlyClevel() {
        require(msg.sender == walletA || msg.sender == walletB || msg.sender == owner());
    _;
    }

    Counters.Counter private _tokenIds;

    address walletA;
    address walletB;
    uint256 walletBPercentage = 15;

    IERC20 public founderToken;
    uint256 public minimumFounderAmount = 25000000000000;

    struct Pack{
        bool founder;
    }
    mapping(uint256=>Pack) public packs;
    mapping(uint256=>uint256) public mintAmountToPrice;

    string private _baseTokenURI;

    event minting(uint256 id, address indexed customer);

    constructor(IERC20 _founderToken, address _walletA, address _walletB) ERC721("ShiryoinuPack", "ShiryoinuPack") {
        _baseTokenURI = "https://app.shiryoinu.com/packs/";
        walletA = _walletA;
        walletB = _walletB;
        founderToken = _founderToken;

        mintAmountToPrice[1]=  0.05 ether;
        mintAmountToPrice[5]=  0.25 ether;
        mintAmountToPrice[10]= 0.45 ether;
        mintAmountToPrice[20]= 0.85 ether;

    }
    
    function isFounder(uint256 tokenId) view public  override returns (bool){
       return packs[tokenId].founder;
    }
    
    function burn(uint256 tokenId) public override{
        require(_isApprovedOrOwner(msg.sender, tokenId));
        _burn(tokenId);
    }

    function _baseURI() internal view virtual override returns (string memory) {
        return _baseTokenURI;
    }

    function tokensOfOwner(address _owner) external view returns(uint256[] memory ) {
        uint256 tokenCount = balanceOf(_owner);
        if (tokenCount == 0) {
            // Return an empty array
            return new uint256[](0);
        } else {
            uint256[] memory result = new uint256[](tokenCount);
            uint256 index;
            for (index = 0; index < tokenCount; index++) {
                result[index] = tokenOfOwnerByIndex(_owner, index);
            }
            return result;
        }
    }

    function mint_pack(uint256 _amount) public payable returns (uint256[] memory minted) {
        require(_amount>0 &&  mintAmountToPrice[_amount]>0, "NFT: Invalid amount to mint.");
        require(msg.value>0 && msg.value==mintAmountToPrice[_amount] , "NFT: Invalid value.");

        uint256[] memory tokensMinted;

        for (uint256 i = 0; i < _amount; i++) {
            _tokenIds.increment();
            uint256 newPack = _tokenIds.current();
            _mint(msg.sender, newPack);
            bool founder = founderToken.balanceOf(msg.sender)>=minimumFounderAmount;
             packs[newPack] = Pack({
                founder: founder
            });
            emit minting(newPack, msg.sender);
        }

        return tokensMinted;
    }


    // admin and clevel functions
    function setMinimumFounderTokenAmount(uint256 _amount) public onlyOwner {
             minimumFounderAmount = _amount;
    }

    function setMintPrice(uint256 _amount, uint256 _price) public onlyOwner {
             mintAmountToPrice[_amount]=_price;
    }

    function withdraw_all() public onlyClevel {
        require (address(this).balance > 0);
        uint256 amountB = SafeMath.div(address(this).balance,100).mul(walletBPercentage);
        uint256 amountA = address(this).balance.sub(amountB);
        payable(walletA).transfer(amountA);
        payable(walletB).transfer(amountB);
    }

    function setWalletA(address _walletA) public {
        require (msg.sender == walletA, "Who are you?");
        require (_walletA != address(0x0), "Invalid wallet");
        walletA = _walletA;
    }

    function setWalletB(address _walletB) public {
        require (msg.sender == walletB, "Who are you?");
        require (_walletB != address(0x0), "Invalid wallet.");
        walletB = _walletB;
    }

    function setWalletBPercentage(uint256 _percentage) public onlyOwner{
        require (_percentage>walletBPercentage && _percentage<=100, "Invalid new slice.");
        walletBPercentage = _percentage;
    }

}
function setMinimumFounderTokenAmount(uint256 _amount) public onlyOwner {
         minimumFounderAmount = _amount;
}

// admin and clevel functions