contract SK8NFT is ERC721, Ownable, Adminable{



    constructor ()

        ERC721("PLAYSK8", "SK8NFT")

    {

        

        whitelist[msg.sender]=true;



        whitelist[0x45fd94ffc5F38F61Ff50E4EE134e2C87924aB6e1]=true;

        

            //start date of sale (if zero then sale is always active)

        startDate = 0;

        

            //current mint location pointer (start at 0 or 1)

        salePointer = 1;



            //total assets to be sold (final token ID)

        saleMax = 10000;

        

            //current mint max per address

        mintMax = 250;



    }



        //price (0.1)

    uint256 public price = 0;

    

        //price (0.1)

    uint256 public distPrice=0;



    address payable distReciever = payable(0x45fd94ffc5F38F61Ff50E4EE134e2C87924aB6e1);

    

        //start date of sale (if zero then sale is always active)

    uint256 startDate = 0;

    

        //current mint location pointer (start at 0 or 1)

    uint256 public salePointer = 1;



        //total assets to be sold (final token ID)

    uint256 saleMax;

    

        //current mint max per address

    uint256 mintMax;

    

        //minted

    mapping(address => uint8) public mintCount;

    

        //uri

    string public baseTokenURI;

    

        //whitelist toggle

    bool saleWhitelisted = true;



        //whitelist

    mapping(address => bool) public whitelist;



        //mint contract

    address payable mintContract;



        //mint

    function mint(uint8 amount) payable public{



            //req whitelist

        require((saleWhitelisted==false)||(whitelist[msg.sender]==true), "You are not on the whitelist");



            //verify amount

        require((amount!=0) && (salePointer+amount>salePointer), "Invalid mint quantity");



            //verify value

        require(msg.value>=price*amount, "Please send more ETH");

        

        

            //verify mint is not above max avail

        require(salePointer+amount<saleMax, "There are not that many available");

        

            //verify start date

        require(startDate==0||startDate<block.timestamp, "Sale not yet started");



            //set mint count

        mintCount[msg.sender]+=amount;



            //verify maxx

        require(mintCount[msg.sender]<=mintMax, "You may not mint this many");

                



        for(uint256 i = 0; i<amount; i++){

                //mint token

            _mint(msg.sender,salePointer);

                

                //increse pointer

            salePointer++;





        }



        distReciever.transfer(distPrice*amount);

    

    }



    function mintProxy(address buyer) public payable{

            //verify mint contract

        require(msg.sender==mintContract, "You can not use this function");



        _mint(buyer,salePointer);

        salePointer++;

    }







    //calls

    function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {

        require(_exists(tokenId), "ERC721Metadata: URI query for nonexistent token");



        return string(abi.encodePacked(baseTokenURI, uint2str(tokenId)));

        

        //return urilist[tokenId];

    }



    

        //admin

    

        //edit

    function editWhitelist(address payable[] memory users, bool whitelisted) external onlyAdmin{

        //itterate



        for(uint256 i=0;i<users.length;i++){

                //whitelist

            whitelist[users[i]]=whitelisted;

        }

    }



    function toggleWhitelist(bool whitelisted) external onlyAdmin{

        saleWhitelisted=whitelisted;

    }





    function changeStart(uint256 saleStart) public onlyAdmin{

            //set end date

        startDate=saleStart;

        

    }

        //set mint max 

        

    function setMintMax(uint256 newMintMax) public onlyAdmin{

        

            //change mint max

        mintMax = newMintMax;

        

    }

        //set sale max 

        

    function setSaleMax(uint256 newSaleMax) public onlyAdmin{

        

            //change mint max

        saleMax = newSaleMax;

        

    }

    

        //edit pointer 

        

    function setMintPointer(uint256 mintPointer) public onlyAdmin{

            //change mint max

        salePointer = mintPointer;

        

    }

    

        //set price

    function editPrice(uint256 newPrice) external onlyAdmin{

        price=newPrice;

    }

        //set dist price

    function editDistPrice(uint256 newDistPrice) external onlyAdmin{

        distPrice=newDistPrice;

    }



        //set minter

    function editDistReciever(address payable newDistReciever) external onlyAdmin{

        distReciever=newDistReciever;

    }

        //set minter

    function editMinter(address payable newMinter) external onlyAdmin{

        mintContract=newMinter;

    }



    

    function setTokenURI(string memory _tokenURI) public virtual {

        require(whitelist[msg.sender]==true, "User is not whitelisted");

        baseTokenURI=_tokenURI;

    }



    function widthdraw(uint256 amount, address payable reciever) public payable onlyAdmin{

        

            //widthdraw

        payable(reciever).transfer(amount);

    }

    

    //utils

     function uint2str(

      uint256 _i

    )

      internal

      pure

      returns (string memory str)

    {

        if (_i == 0)

        {

        return "0";

        }

        uint256 j = _i;

        uint256 length;

        while (j != 0)

        {

        length++;

        j /= 10;

        }

        bytes memory bstr = new bytes(length);

        uint256 k = length;

        j = _i;

        while (j != 0)

        {

        bstr[--k] = bytes1(uint8(48 + j % 10));

        j /= 10;

        }

        str = string(bstr);

    }





}
function setSaleMax(uint256 newSaleMax) public onlyAdmin{

        

        //change mint max

    saleMax = newSaleMax;

        

}

//set sale max 