contract CeliachiaFacile is ERC721Enumerable, Ownable {
    using Strings for uint256;

    string public baseURI;
    string public baseExtension = ".json";
    uint256 public cost = 130000000000000000;
    uint256 public maxSupply = 283;
    bool public public_paused = false;
    bool public pre_paused = false;
    mapping (address => bool) public presaleWallets;
    uint256 public preCost = 120000000000000000;

    constructor(string memory _initBaseURI)
        ERC721("Celiachia Facile World", "CFW")
        {
            setBaseURI(_initBaseURI);
        }

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

    // public
    function mint() public payable {
        uint256 supply = totalSupply();
        require(!public_paused, "Public Sale has not started yet");
        require(supply < maxSupply, "Amount exceeds Max Supply");


        if (msg.sender != owner()) {
		    require(msg.value >= cost);
        }

        _safeMint(msg.sender, supply+1);
    }

    function preMint() public payable {
        uint256 supply = totalSupply();

        require(!pre_paused, "Public Sale has not started yet");
        require(supply < maxSupply, "Amount exceeds Max Supply");
        


        if (msg.sender != owner()) {
            require(presaleWallets[msg.sender] == true, "You are not listed for Pre-sale");
		    require(msg.value >= preCost);
        }

        _safeMint(msg.sender, supply+1);
    }
    
    function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {
        require(_exists(tokenId), "ERC721Metadata: URI query for nonexistent token");

        string memory currentBaseURI = _baseURI();
        return
            bytes(currentBaseURI).length > 0
                ? string(
                    abi.encodePacked(
                        currentBaseURI,
                        tokenId.toString(),
                        baseExtension
                    )
                )
                : "";
    }

    //only owner
    function setCost(uint256 _newCost) public onlyOwner {
        cost = _newCost;
    }

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

    function setBaseExtension(string memory _newBaseExtension) public onlyOwner {
        baseExtension = _newBaseExtension;
    }

    function startPublicSale() public onlyOwner {
        public_paused = false;
    }

    function stopPublicSale() public onlyOwner {
        public_paused = true;
    }
    
   
    function startPreSale() public onlyOwner {
        pre_paused = false;
    }

    function stopPreSale() public onlyOwner {
        pre_paused = true;
    }

    function whitelistAddress (address[] memory users) public onlyOwner {
        for (uint i = 0; i < users.length; i++) {
            presaleWallets[users[i]] = true;
        }
    }

    function setPreCost(uint256 _newPreCost) public onlyOwner {
        preCost = _newPreCost;
    }

    function withdraw() public payable onlyOwner {
        payable(msg.sender).transfer(address(this).balance);
    }
}
function setCost(uint256 _newCost) public onlyOwner {
    cost = _newCost;
}

//only owner