contract Phouns is ERC721, Ownable, PaymentSplitter {
    using Counters for Counters.Counter;
    
    Counters.Counter private _tokenIdCounter;
    bool public openMint = false;
    
    bool private initialized = false;
    
    uint256 public tokenPrice = .02 ether;
    
    uint256 public constant maxTokens = 5000;

    uint256 public constant maxFree = 2000;

    uint public maxFreeMintPerWallet = 20;

    mapping(address => uint) public addressFreeMinted;

    string private _contractURI;
    
    uint256 public maxMintsPerTx = 5;
    
    constructor() public ERC721("Phouns", "PHOUNS") {}

    //Set Base URI
    function setBaseURI(string memory _baseURI) external onlyOwner {
        _setBaseURI(_baseURI);
    }
    
    function flipMintState() public onlyOwner {
        openMint = !openMint;
    }

    function initializePaymentSplitter (address[] memory payees, uint256[] memory shares_) external onlyOwner {
        require (!initialized, "Payment Split Already Initialized!");
        require(payees.length == shares_.length, "PaymentSplitter: payees and shares length mismatch");
        require(payees.length > 0, "PaymentSplitter: no payees");

        for (uint256 i = 0; i < payees.length; i++) {
            _addPayee(payees[i], shares_[i]);
        }
        initialized=true;
    }

    function freeMint(uint256 quantity) external {
        require(openMint, "mint not open");
        require(totalSupply() + quantity <= maxFree, "theres no free mints remaining");
        require(quantity <= maxMintsPerTx, "trying to mint too many at a time");
        require(addressFreeMinted[msg.sender] < maxFreeMintPerWallet, "can only mint 20 for free per address");
        
        addressFreeMinted[msg.sender] += quantity;
        for(uint256 i = 0; i < quantity; i++) {
            safeMint(msg.sender);
        }
    }
    
    function mint(uint256 quantity) external payable {
        require(totalSupply() + quantity <= maxTokens, "minting this many would exceed supply");
        require(quantity <= maxMintsPerTx, "trying to mint too many at a time");
        require(msg.value >= tokenPrice * quantity, "not enough ether sent");
        require(openMint, "mint not open");
        for (uint256 i = 0; i < quantity; i++) {
            safeMint(msg.sender);
        }
    }

    function safeMint(address to) internal {
        uint256 tokenId = _tokenIdCounter.current();
        _tokenIdCounter.increment();
        _safeMint(to, tokenId);
    }

    function totalSupply() public view override returns (uint) {
        return _tokenIdCounter.current();
    }

    function setPrice(uint newPrice) external onlyOwner {
        tokenPrice = newPrice;
    }
}
/**
 * @title Phouns contract
 * @dev Extends ERC721 Non-Fungible Token Standard basic implementation
 */
function setBaseURI(string memory _baseURI) external onlyOwner {
    _setBaseURI(_baseURI);
}

//Set Base URI