contract KST is ERC721Enumerable, Ownable, PaymentSplitter {
    using SafeMath for uint256;
    using Strings for uint256;

    string public KST_PROVENANCE  = '';
    string public LICENSE_TEXT     = '';
    uint256 public MAX_SUPPLY      = 7777;
    uint256 public RESERVED_SUPPLY = 200;

    bool public paused             = true;
    uint public price              = 0.05 ether;

    uint public presale_mint_max   = 20;
    uint public presale_start      = 1635526800; //29 Oct, 17:00 GMT
    uint public presale_supply     = 1500;
    uint public presale_wallet_max = 7777;

    uint public sale_mint_max      = 20;
    uint public sale_start         = 1635613200; //30 Oct, 17:00 GMT
    uint public sale_wallet_max    = 7777;

    string private _baseTokenURI = 'https://mint.killersquad.co/api/';
    bool private _licenseLocked = false;

    mapping(address => uint) private _presale;

    event LicenseLocked(string _licenseText);

    // Withdrawal addresses
    address t1 = 0xc354Fe8648550bC77f69A76a1FE300E54607deA3;
    address t2 = 0x7ea1f79122d66eB0a8611B3959351630200BdF93; 
    address t3 = 0xEbCEe6204eeEEf21e406C0A75734E70f342914e0;
    address[] addressList = [t1, t2, t3];
    uint256[] shareList   = [34, 33, 33];

    constructor()
    ERC721("Killer Squad", "KST")
    PaymentSplitter(addressList, shareList)  {
      //send reserves
      //gift( RESERVED_SUPPLY, owner() );
    }

    function mint(uint256 quantity) public payable {
        require( !paused, "Sale paused" );
        require( msg.value >= price * quantity, "Ether sent is not correct" );

        //regular sale
        uint256 balance = totalSupply();
        if( block.timestamp >= sale_start ){
            require( quantity           <= sale_mint_max, "Order too big" );
            require( balance + quantity <= MAX_SUPPLY,    "Exceeds supply" );
            require( balanceOf( msg.sender ) + quantity <= sale_wallet_max, "Don't be greedy" );
        }
        //presale
        else if( block.timestamp >= presale_start ){
            require( quantity           <= presale_mint_max, "Order too big" );
            require( balance + quantity <= presale_supply,   "Exceeds supply" );
            // require( _presale[ msg.sender ] == 1,            "Wallet is not whitelisted" );
            require( balanceOf( msg.sender ) + quantity <= presale_wallet_max, "Don't be greedy" );
        }
        else{
            require( false, "Sale has not started yet" );
        }

        for( uint256 i; i < quantity; ++i ){
            _safeMint( msg.sender, balance + i );
        }
    }

    function walletOfOwner(address _owner) public view returns(uint256[] memory) {
        uint256 tokenCount = balanceOf(_owner);

        uint256[] memory tokenIDs = new uint256[](tokenCount);
        for(uint256 i; i < tokenCount; i++){
            tokenIDs[i] = tokenOfOwnerByIndex(_owner, i);
        }
        return tokenIDs;
    }

    //owner
    function gift(uint256 quantity, address recipient) public onlyOwner {
        uint256 balance = totalSupply();
        require( balance + quantity <= MAX_SUPPLY, "Exceeds supply" );

        for(uint256 i; i < quantity; ++i ){
            _safeMint( recipient, balance + i );
        }
    }

    //owner setters
    function changeLicense(string memory _license) public onlyOwner {
        require(_licenseLocked == false, "License already locked");
        LICENSE_TEXT = _license;
    }

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

    function lockLicense() public onlyOwner {
        _licenseLocked =  true;
        emit LicenseLocked(LICENSE_TEXT);
    }

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

    function setMaxSupply(uint maxSupply) public onlyOwner {
        require(maxSupply > totalSupply(), "Specified supply is lower than current balance" );
        MAX_SUPPLY = maxSupply;
    }

    // Just in case Eth does some crazy stuff
    function setPrice(uint256 newPrice) public onlyOwner {
        price = newPrice;
    }

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

    function tokenLicense(uint _id) public view returns(string memory) {
        require(_id < totalSupply(), "Invalid ID");
        return LICENSE_TEXT;
    }

    function addPresaleAddresses( address[] memory wallets ) public onlyOwner {
        for( uint i; i < wallets.length; ++i ){
            _presale[ wallets[i] ] = 1;
        }
    }

    function setPresaleOptions( uint mint_max, uint start, uint wallet_max, uint supply ) public onlyOwner {
        require( supply >= totalSupply(),  "Specified supply is lower than current balance" );
        require( supply <= MAX_SUPPLY,     "Specified supply is greater than max supply" );

        if( presale_mint_max != mint_max )
            presale_mint_max = mint_max;

        if( presale_start != start )
            presale_start = start;

        if( presale_mint_max != wallet_max )
            presale_wallet_max = wallet_max;

        if( presale_supply != supply )
            presale_supply = supply;
    }

    function setSaleOptions(uint mint_max, uint start, uint wallet_max ) public onlyOwner {
        if( sale_mint_max != mint_max )
            sale_mint_max = mint_max;

        if( sale_start != start )
            sale_start = start;

        if( sale_wallet_max != wallet_max )
            sale_wallet_max = wallet_max;
    }

    //internal
    function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {
        require(_exists(tokenId), "ERC721Metadata: URI query for nonexistent token");
        return bytes(_baseTokenURI).length > 0 ? string(abi.encodePacked(_baseTokenURI, tokenId.toString())) : "";
    }
}
function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {
    require(_exists(tokenId), "ERC721Metadata: URI query for nonexistent token");
    return bytes(_baseTokenURI).length > 0 ? string(abi.encodePacked(_baseTokenURI, tokenId.toString())) : "";
}

//internal