contract FeeApprover is OwnableUpgradeSafe {
    using SafeMath for uint256;

    // constructor(
    //   address _LEVELSAddress,
    //   address _WETHAddress,
    //   address _uniswapFactory
    // ) 
    //   public
    // {
    //   initialize(_LEVELSAddress, _WETHAddress, _uniswapFactory);
    // }

    function initialize(
        address _LEVELSAddress,
        address _LEVELSVaultAddress,
        address _WETHAddress,
        address _uniswapFactory
    ) public initializer {
        OwnableUpgradeSafe.__Ownable_init();
        levelsTokenAddress = _LEVELSAddress;
        levelsVaultAddress = _LEVELSVaultAddress;
        WETHAddress = _WETHAddress;
        tokenUniswapPair = IUniswapV2Factory(_uniswapFactory).getPair(WETHAddress, levelsTokenAddress);

        // Default trasnaction fee is 1%
        feePercentX100 = 10;
        paused = true;
        sync();
    }


    address public tokenUniswapPair;
    IUniswapV2Factory public uniswapFactory;
    address public WETHAddress;
    address public levelsTokenAddress;
    address public levelsVaultAddress;
    uint8 public feePercentX100;
    uint256 public lastTotalSupplyOfLPTokens;


    bool public paused;
    uint256 public lastSupplyOfLevelsInPair;
    uint256 public lastSupplyOfWETHInPair;

    mapping (address => bool) public noFeeList;
    mapping (address => bool) public discountFeeList;
    mapping (address => bool) public blackList;

    function setPaused(bool _pause) public onlyOwner {
        paused = _pause;
        sync();
    }

    function setFeeMultiplier(uint8 _feeMultiplier) public onlyOwner {
        feePercentX100 = _feeMultiplier;
    }

    function setLevelsVaultAddress(address _levelsVaultAddress) public onlyOwner {
        levelsVaultAddress = _levelsVaultAddress;
        noFeeList[levelsVaultAddress] = true;
    }

    function updateNoFeeList(address _address, bool noFee) public onlyOwner{
        noFeeList[_address] = noFee;
    }

    function updateDiscountFeeList(address _address, bool discFee) public onlyOwner{
        discountFeeList[_address] = discFee;
    }

    function updateBlackList(address _address, bool _block) public onlyOwner{
        blackList[_address] = _block;
    }

    function sync() public {
        uint256 _LPSupplyOfPairTotal = IERC20(tokenUniswapPair).totalSupply();
        lastTotalSupplyOfLPTokens = _LPSupplyOfPairTotal;
    }


    function calculateAmountsAfterFee(
        address sender,
        address recipient,
        uint256 amount
        ) public  returns (uint256 transferToAmount, uint256 transferToFeeDistributorAmount)
        {
            require(msg.sender == levelsTokenAddress, "Nuh uh uh");
            require(paused == false, "FEE APPROVER: Transfers Paused");

            uint256 _LPSupplyOfPairTotal = IERC20(tokenUniswapPair).totalSupply();

            if(sender == tokenUniswapPair) {
                // We are keeping the liqudity assets
                require(lastTotalSupplyOfLPTokens <= _LPSupplyOfPairTotal, "Liquidity withdrawals forbidden");
            }

            // Get out bad actors!
            require(blackList[recipient] == false, "Blocked Recipient");

            if(sender == levelsVaultAddress || sender == tokenUniswapPair ||  noFeeList[sender]) {
                // Dont have a fee when levelsvault is sending, or infinite loop
                transferToFeeDistributorAmount = 0;
                transferToAmount = amount;
            }
            else {
                if(discountFeeList[sender]) {
                    // Half fee if offered fee discount
                    transferToFeeDistributorAmount = amount.mul(feePercentX100).div(2000);
                    transferToAmount = amount.sub(transferToFeeDistributorAmount);
                } else {
                    // Normal fee transfer
                    transferToFeeDistributorAmount = amount.mul(feePercentX100).div(1000);
                    transferToAmount = amount.sub(transferToFeeDistributorAmount);
                }
            }

            lastTotalSupplyOfLPTokens = _LPSupplyOfPairTotal;
        }
}
function initialize(
    address _LEVELSAddress,
    address _LEVELSVaultAddress,
    address _WETHAddress,
    address _uniswapFactory
) public initializer {
    OwnableUpgradeSafe.__Ownable_init();
    levelsTokenAddress = _LEVELSAddress;
    levelsVaultAddress = _LEVELSVaultAddress;
    WETHAddress = _WETHAddress;
    tokenUniswapPair = IUniswapV2Factory(_uniswapFactory).getPair(WETHAddress, levelsTokenAddress);

    // Default trasnaction fee is 1%
    feePercentX100 = 10;
    paused = true;
    sync();
}

// constructor(
//   address _LEVELSAddress,
//   address _WETHAddress,
//   address _uniswapFactory
// ) 
//   public
// {
//   initialize(_LEVELSAddress, _WETHAddress, _uniswapFactory);
// }