contract WickedWillysBE is ERC721, PaymentSplitter, Ownable {
    
    using SafeMath for uint256;

    // Constants
    uint public constant maxTokenPurchase = 5;
    uint256 public constant MAX_TOKENS = 1024;

    // Variables
    uint256 public tokenPrice = 25000000000000000; // 0.025 ETH
    bool public saleIsActive = false;

    // Withdraw Addresses
    address[] private teamWallets = [
        0x214B56E7121aB36977F9B4920E04263d1FAabb8c, // 70
        0x39010C2E22281629E9E7aC94f5c78dB38FDD8a7E  // 30
    ];

    uint256[] private teamShares = [70,30];

    // To be decided
    string public TOKEN_PROVENANCE = ""; // IPFS URL WILL BE ADDED WHEN TOKENS ARE ALL SOLD OUT
    string public LICENSE_TEXT = ""; // IT IS WHAT IT SAYS 
    bool licenseLocked = false; // TEAM CAN'T EDIT THE LICENSE AFTER THIS GETS TRUE
    
    event licenseisLocked(string _licenseText);

    constructor()
        PaymentSplitter(teamWallets, teamShares)
        ERC721("Wicked Willys Bloot Edition", "BLOOTWILLYS")
    {}

    // Make sale Active/Inactive
    function flipSaleState() public onlyOwner {
        saleIsActive = !saleIsActive;
    }

    // Return Sale Active/Inactive
    function getSalesState() public view returns (bool){
        return saleIsActive;
    }

    // Just in case ETH does something silly
    function setTokenPrice(uint256 newPrice) public onlyOwner {
        tokenPrice = newPrice;
    }

    function setProvenanceHash(string memory provenanceHash) public onlyOwner {
        TOKEN_PROVENANCE = provenanceHash;
    }

    function setBaseURI(string memory baseURI) public onlyOwner {
        _setBaseURI(baseURI);
    }
    
    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;
        }
    }
    
    // Returns the license for tokens
    function tokenLicense(uint _id) public view returns(string memory) {
        require(_id < totalSupply(), "Choose a token within range");
        return LICENSE_TEXT;
    }
    
    // Change the license
    function changeLicense(string memory _license) public onlyOwner {
        require(licenseLocked == false, "The license is already locked");
        LICENSE_TEXT = _license;
    }

    // Locks the license to prevent further changes 
    function lockLicense() public onlyOwner {
        licenseLocked =  true;
        emit licenseisLocked(LICENSE_TEXT);
    }

    function getBalance() public view onlyOwner returns (uint){
        uint balance = address(this).balance;
        return balance;
    }

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

    // Withdraw balance to wallets per share allocation
    function withdrawShares() public onlyOwner {
        for (uint256 i = 0; i < teamWallets.length; i++) {
            address payable wallet = payable(teamWallets[i]);
            release(wallet);
        }
    }
    
    function mintToken(uint numberOfTokens) public payable {
        require(saleIsActive, "Sale must be active to mint Token");
        require(numberOfTokens > 0 && numberOfTokens <= maxTokenPurchase, "Can only mint 3 tokens at a time");
        require(totalSupply().add(numberOfTokens) <= MAX_TOKENS, "Purchase would exceed max supply of Tokens");
        require(msg.value >= tokenPrice.mul(numberOfTokens), "Ether value sent is not correct");
        
        for(uint i = 0; i < numberOfTokens; i++) {
            uint mintIndex = totalSupply();
            if (totalSupply() < MAX_TOKENS) {
                _safeMint(msg.sender, mintIndex);
            }
        }
    }
    
}
function setTokenPrice(uint256 newPrice) public onlyOwner {
        tokenPrice = newPrice;
    }
// Just in case ETH does something silly