contract PunkLoot is ERC721, ReentrancyGuard, Ownable {
    using SafeMath for uint256;

    string public PROVENANCE = "";
    uint256 public lootersPrice = 50000000000000000; //0.05 ETH
    uint256 public publicPrice = 150000000000000000; //0.15 ETH
    bool public saleIsActive = true;
    bool public privateSale = true;

    //Loot Contract
    address public lootAddress = 0xFF9C1b15B16263C61d017ee9F65C50e4AE0113D7;
    LootInterface lootContract = LootInterface(lootAddress);

    constructor() ERC721("Punk Loot", "PKL") {
    }

    function withdraw() public onlyOwner {
        uint balance = address(this).balance;
        address payable owner = payable(msg.sender);
        owner.transfer(balance);
    }

    function deposit() public payable onlyOwner {}

    function flipSaleState() public onlyOwner {
        saleIsActive = !saleIsActive;
    }

    function endPrivateSale() public onlyOwner {
        require(privateSale);
        privateSale = false;
    }

    function setLootersPrice(uint256 newPrice) public onlyOwner {
        lootersPrice = newPrice;
    }

    function setPublicPrice(uint256 newPrice) public onlyOwner {
        publicPrice = newPrice;
    }

    function setBaseURI(string memory baseURI) public onlyOwner {
        _setBaseURI(baseURI);
    }

    function setProvenance(string memory prov) public onlyOwner {
        PROVENANCE = prov;
    }

    //Private sale minting (reserved for Loot owners)
    function mintWithLoot(uint lootId) public payable nonReentrant {
        require(privateSale, "Private sale minting is over");
        require(saleIsActive, "Sale must be active to mint");
        require(lootersPrice <= msg.value, "Ether value sent is not correct");
        require(lootContract.ownerOf(lootId) == msg.sender, "Not the owner of this loot");
        require(!_exists(lootId), "This token has already been minted");

        _safeMint(msg.sender, lootId);
    }

    function multiMintWithLoot(uint[] memory lootIds) public payable nonReentrant {
        require(privateSale, "Private sale minting is over");
        require(saleIsActive, "Sale must be active to mint");
        require((lootersPrice * lootIds.length) <= msg.value, "Ether value sent is not correct");
        
        for (uint i=0; i<lootIds.length; i++) {
            require(lootContract.ownerOf(lootIds[i]) == msg.sender, "Not the owner of this loot");
            require(!_exists(lootIds[i]), "One of these tokens has already been minted");
            _safeMint(msg.sender, lootIds[i]);
        }
    }

    //Public sale minting
    function mint(uint lootId) public payable nonReentrant {
        require(!privateSale, "Public sale minting not started");
        require(saleIsActive, "Sale must be active to mint");
        require(publicPrice <= msg.value, "Ether value sent is not correct");
        require(lootId > 0 && lootId < 8001, "Token ID invalid");
        require(!_exists(lootId), "This token has already been minted");

        _safeMint(msg.sender, lootId);
    }

    function multiMint(uint[] memory lootIds) public payable nonReentrant {
        require(!privateSale, "Public sale minting not started");
        require(saleIsActive, "Sale must be active to mint");
        require((publicPrice * lootIds.length) <= msg.value, "Ether value sent is not correct");
        
        for (uint i=0; i<lootIds.length; i++) {
            require(lootIds[i] > 0 && lootIds[i] < 8001, "Token ID invalid");
            require(!_exists(lootIds[i]), "One of these tokens have already been minted");
            _safeMint(msg.sender, lootIds[i]);
        }
    }

    function emergencyMint(uint[] memory lootIds) public onlyOwner {
        require(!saleIsActive, "Sale must be not active");
        for (uint i=0; i<lootIds.length; i++) {
            require(lootIds[i] > 0 && lootIds[i] < 8001, "Token ID invalid");
            require(!_exists(lootIds[i]), "One of these tokens have already been minted");
            _safeMint(msg.sender, lootIds[i]);
        }
    }
}
/**
 * @title PunkLoot contract
 * @dev Extends ERC721 Non-Fungible Token Standard basic implementation
 */
function mint(uint lootId) public payable nonReentrant {
        require(!privateSale, "Public sale minting not started");
        require(saleIsActive, "Sale must be active to mint");
        require(publicPrice <= msg.value, "Ether value sent is not correct");
        require(lootId > 0 && lootId < 8001, "Token ID invalid");
        require(!_exists(lootId), "This token has already been minted");

        _safeMint(msg.sender, lootId);
    }
//Public sale minting