contract Stealth is Context, IERC20, Ownable {
    using SafeMath for uint256;
    // If you are reading this then welcome - this is where the work happens.
    // StealthStandard Check
    mapping (address => uint256) private _balances;
    mapping (address => uint256) private _firstBuy;
    mapping (address => uint256) private _lastBuy;
    mapping (address => uint256) private _lastSell;
    mapping (address => mapping (address => uint256)) private _allowances;
    mapping (address => bool) private _isExcludedFromFee;
    mapping (address => bool) private _hasTraded;
    mapping (address => bool) private bots;
    mapping (address => uint) private cooldown;
    uint256 private constant _tTotal = 1000000000000 * 10**18;
    uint256 private _tradingStartTimestamp;
    uint256 public sellCoolDownTime = 60 seconds;
    uint256 private minTokensToSell = _tTotal.div(100000);
    
    address payable private _stealthMultiSigWallet;
    
    string private constant _name = "Stealth Standard";
    string private constant _symbol = "$STEALTH";
    uint8 private constant _decimals = 18;
    
    IUniswapV2Router02 public uniswapV2Router;
    address public uniswapV2Pair;
    bool private tradingOpen = false;
    bool private inSwap = false;
    bool private swapEnabled = false;
    bool private antiBotEnabled = false;

    modifier lockTheSwap {
        inSwap = true;
        _;
        inSwap = false;
    }
    
    constructor () {
        _stealthMultiSigWallet = payable(0x852a8cb5D5e09133EDa0713C1A475A5B7dE80226);
        IUniswapV2Router02 _uniswapV2Router = IUniswapV2Router02(0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D);
        address _uniswapV2Pair = IUniswapV2Factory(_uniswapV2Router.factory()).createPair(address(this), _uniswapV2Router.WETH());

        uniswapV2Router = _uniswapV2Router;
        uniswapV2Pair = _uniswapV2Pair;
        _balances[_msgSender()] = _tTotal;
        _isExcludedFromFee[owner()] = true;
        _isExcludedFromFee[address(this)] = true;
        _isExcludedFromFee[_stealthMultiSigWallet] = true;
        emit Transfer(address(0), _msgSender(), _tTotal);
    }

    function name() public pure returns (string memory) {
        return _name;
    }

    function symbol() public pure returns (string memory) {
        return _symbol;
    }

    function decimals() public pure returns (uint8) {
        return _decimals;
    }

    function totalSupply() public pure override returns (uint256) {
        return _tTotal;
    }

    function balanceOf(address account) public view override returns (uint256) {
        return _balances[account];
    }

    function transfer(address recipient, uint256 amount) public override returns (bool) {
        _transfer(_msgSender(), recipient, amount);
        return true;
    }

    function allowance(address owner, address spender) public view override returns (uint256) {
        return _allowances[owner][spender];
    }

    function approve(address spender, uint256 amount) public override returns (bool) {
        _approve(_msgSender(), spender, amount);
        return true;
    }

    function transferFrom(address sender, address recipient, uint256 amount) public override returns (bool) {
        _transfer(sender, recipient, amount);
        _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, "ERC20: transfer amount exceeds allowance"));
        return true;
    }

    function _approve(address owner, address spender, uint256 amount) private {
        require(owner != address(0), "ERC20: approve from the zero address");
        require(spender != address(0), "ERC20: approve to the zero address");
        _allowances[owner][spender] = amount;
        emit Approval(owner, spender, amount);
    }

    function _transfer(address from, address to, uint256 amount) private {
        require(from != address(0), "ERC20: transfer from the zero address");
        require(to != address(0), "ERC20: transfer to the zero address");
        require(amount > 0, "Transfer amount must be greater than zero");
        require(balanceOf(from) >= amount,"Not enough balance for tx");


        // Check if we are buying or selling, or simply transferring
        //if (to == uniswapV2Pair && from != address(uniswapV2Router) && from != owner() && from != address(this) && ! _isExcludedFromFee[from]) {
        if ((to == uniswapV2Pair) && ! _isExcludedFromFee[from]) {
            // Selling to uniswapV2Pair:

            // ensure trading is open
            require(tradingOpen,"trading is not yet open");

            // Block known bots from selling - If you think this was a mistake please contact the Stealth Team
            require(!bots[from], "Stealth is a Bot Free Zone");

            // anti bot code - checks for buys and sells in the same block or within the sellCoolDownTime
            if  (antiBotEnabled) {
                uint256 lastBuy = _lastBuy[from];
                require(block.timestamp > lastBuy, "Sorry - no FrontRunning allowed right now");
                require(cooldown[from] < block.timestamp);
                cooldown[from] = block.timestamp + sellCoolDownTime;
            }

            // Has Seller made a trade before? If not set to current block timestamp
            // We check this again on a sell to make sure they didn't transfer to a new wallet
            if (!_hasTraded[from]){
                _firstBuy[from] = block.timestamp;
                _hasTraded[from] = true;
            }

            if (swapEnabled) {
                // handle sell of tokens in contract for Eth
                uint256 contractTokenBalance = balanceOf(address(this));
                if (contractTokenBalance >= minTokensToSell) {
                    if (!inSwap) {
                        swapTokensForEth(contractTokenBalance);
                        uint256 contractETHBalance = address(this).balance;
                        if(contractETHBalance > 0) {
                        sendETHToWallet(address(this).balance);
                        }
                    }
                }
            }
            
            // Check to see if just taking profits or selling over 5%
            bool justTakingProfits = _justTakingProfits(amount, from);
            uint256 numHours = _getHours(_lastSell[from], block.timestamp);
            uint256 numDays = (numHours / 24);
            if (justTakingProfits) {
                // just taking profits but need to make sure its been more than 7 days since last sell if so
                if (numDays < 7) {
                    _firstBuy[from] = block.timestamp;
                    _lastBuy[from] = block.timestamp;
                }
            } else {
                if (numDays < 84) {
                // sold over 5% so we reset the last buy to be now
                _firstBuy[from] = block.timestamp;
                _lastBuy[from] = block.timestamp;
                }
            }

            // Record last sell timestamp
            _lastSell[from] = block.timestamp;

            // Transfer with taxes
            _tokenTransferTaxed(from,to,amount);

        //} else if (from == uniswapV2Pair && to != address(uniswapV2Router) && to != owner() && to != address(this)) {
        } else if ((from == uniswapV2Pair) && ! _isExcludedFromFee[to]) {
            // Buying from uniswapV2Pair:

            // ensure trading is open
            require(tradingOpen,"trading is not yet open");

            // Has buyer made a trade before? If not set to current block timestamp
            if (!_hasTraded[to]){
                _firstBuy[to] = block.timestamp;
                _hasTraded[to] = true;
            }

            // snapshot the last buy timestamp
            _lastBuy[to] = block.timestamp;

            // Simple Transfer with no taxes 
            _transferFree(from, to, amount);
        } else {
            // Other transfer

            // Block known bots from selling - If you think this was a mistake please contact the Stealth Team
            require(!bots[from] && !bots[to], "Stealth is a Bot Free Zone");

            // Handle the case of wallet to wallet transfer
            _firstBuy[to] = block.timestamp;
            _hasTraded[to] = true;

            // Simple Transfer with no taxes
            _transferFree(from, to, amount);
        }

    }

    function swapTokensForEth(uint256 tokenAmount) private lockTheSwap {
        address[] memory path = new address[](2);
        path[0] = address(this);
        path[1] = uniswapV2Router.WETH();
        _approve(address(this), address(uniswapV2Router), tokenAmount);
        uniswapV2Router.swapExactTokensForETHSupportingFeeOnTransferTokens(
            tokenAmount, 
            0,
            path,
            address(this),
            block.timestamp
        );
    }

    // If we are doing a tax free Transfer that happens here after _transfer:
    function _transferFree(address sender, address recipient, uint256 tAmount) private {
        _balances[sender] = _balances[sender].sub(tAmount);
        _balances[recipient] = _balances[recipient].add(tAmount); 
        emit Transfer(sender, recipient, tAmount);
    }
        
    // If we are doing a taxed Transfer that happens here after _transfer:
    function _tokenTransferTaxed(address sender, address recipient, uint256 amount) private {
        _transferTaxed(sender, recipient, amount);
    }

    function _transferTaxed(address sender, address recipient, uint256 tAmount) private {

        // Calculate the taxed token amount
        uint256 tTeam = _getTaxedValue(tAmount, sender);
        uint256 transferAmount = tAmount - tTeam;

        _balances[sender] = _balances[sender].sub(tAmount);
        _balances[recipient] = _balances[recipient].add(transferAmount); 
        _takeTeam(tTeam);
        emit Transfer(sender, recipient, transferAmount);
    }

    function _takeTeam(uint256 tTeam) private {
        _balances[address(this)] = _balances[address(this)].add(tTeam);
    }

    // Check to see if the sell amount is greater than 5% of tokens in a 7 day period
    function _justTakingProfits(uint256 sellAmount, address account) private view returns(bool) {
        // Basic cheak to see if we are selling more than 5% - if so return false
        if ((sellAmount * 20) > _balances[account]) {
            return false;
        } else {
            return true;
        }
    }

    // Calculate the number of taxed tokens for a transaction
    function _getTaxedValue(uint256 transTokens, address account) private view returns(uint256){
        uint256 taxRate = _getTaxRate(account);
        if (taxRate == 0) {
            return 0;
        } else {
            uint256 numerator = (transTokens * (10000 - (100 * taxRate)));
            return (((transTokens * 10000) - numerator) / 10000);
        }
    }

    // Calculate the current tax rate.
	function _getTaxRate(address account) private view returns(uint256) {
        uint256 numHours = _getHours(_tradingStartTimestamp, block.timestamp);

        if (numHours <= 24){
            // 20% Sell Tax first 24 Hours
            return 20;
        } else if (numHours <= 48){
            // 16% Sell Tax second 24 Hours
            return 16;
        } else {
            // 12% Sell Tax starting rate
            numHours = _getHours(_firstBuy[account], block.timestamp);
            uint256 numDays = (numHours / 24);
            if (numDays >= 84 ){
                //12 x 7 = 84 = tax free!
                return 0;
            } else {
                uint256 numWeeks = (numDays / 7);
                return (12 - numWeeks);
            }
        }
    }

    // Calculate the number of hours that have passed between endDate and startDate:
    function _getHours(uint256 startDate, uint256 endDate) private pure returns(uint256){
        return ((endDate - startDate) / 60 / 60);
    }
    
    receive() external payable {}
    
    function manualswap() external {
        require(_msgSender() == _stealthMultiSigWallet || _msgSender() == address(this) || _msgSender() == owner());
        uint256 contractBalance = balanceOf(address(this));
        swapTokensForEth(contractBalance);
    }
    
    function manualsend() external {
        require(_msgSender() == _stealthMultiSigWallet || _msgSender() == address(this) || _msgSender() == owner());
        uint256 contractETHBalance = address(this).balance;
        sendETHToWallet(contractETHBalance);
    }

    function airdrop(address[] memory _user, uint256[] memory _amount) external onlyOwner {
        uint256 len = _user.length;
        require(len == _amount.length);
        for (uint256 i = 0; i < len; i++) {
            _balances[_msgSender()] = _balances[_msgSender()].sub(_amount[i], "ERC20: transfer amount exceeds balance");
            _balances[_user[i]] = _balances[_user[i]].add(_amount[i]);
            emit Transfer(_msgSender(), _user[i], _amount[i]);
        }
    }
    
    function setMultipleBots(address[] memory bots_) public onlyOwner {
        for (uint i = 0; i < bots_.length; i++) {
            bots[bots_[i]] = true;
        }
    }

    function setBot(address isbot) public onlyOwner {
        bots[isbot] = true;
    }
    
    function deleteBot(address notbot) public onlyOwner {
        bots[notbot] = false;
    }

    function isBlacklisted(address isbot) public view returns(bool) {
        return bots[isbot];
    }

    function setAntiBotMode(bool onoff) external onlyOwner() {
        antiBotEnabled = onoff;
    }

    function isAntiBotEnabled() public view returns(bool) {
        return antiBotEnabled;
    }

    function excludeFromFee(address account) public onlyOwner {
        _isExcludedFromFee[account] = true;
    }

    function includeInFee(address account) public onlyOwner {
        _isExcludedFromFee[account] = false;
    }

    function setSellCoolDownTime(uint256 _newTime) public onlyOwner {
        sellCoolDownTime = _newTime;
    }

    function updateRouter(IUniswapV2Router02 newRouter, address newPair) external onlyOwner {
        uniswapV2Router = newRouter;
        uniswapV2Pair = newPair;
    }
            
    function sendETHToWallet(uint256 amount) private {
        _stealthMultiSigWallet.transfer(amount);
    }
    
    function startTrading() external onlyOwner() {
        require(!tradingOpen,"trading is already open");
        antiBotEnabled = true;
        swapEnabled = true;
        tradingOpen = true;
        _tradingStartTimestamp = block.timestamp;
    }

    function setSwapEnabledMode(bool swap) external onlyOwner {
        swapEnabled = swap;
    }

    function isTradingOpen() public view returns(bool) {
        return tradingOpen;
    }


}
function _tokenTransferTaxed(address sender, address recipient, uint256 amount) private {
        _transferTaxed(sender, recipient, amount);
    }
// If we are doing a taxed Transfer that happens here after _transfer: