public class AnalyticsHelper {

    /*

    adb shell setprop log.tag.FA VERBOSE
    adb shell setprop log.tag.FA-SVC VERBOSE
    adb logcat -v time -s FA FA-SVC

     */

    private FirebaseAnalytics firebase = null;

    private static AnalyticsHelper analyticsHelper;

    public static AnalyticsHelper getInstance(Context context) {
        if (analyticsHelper == null) {
            analyticsHelper = new AnalyticsHelper(context);
        }
        return analyticsHelper;
    }

    private AnalyticsHelper(Context context) {
        firebase = FirebaseAnalytics.getInstance(context);
        firebase.setMinimumSessionDuration(3000);
//        firebase.setUserId();
//        firebase.setUserProperty();
    }

    public void logScreenEvent(String screen, String action) {
        Bundle bundle = new Bundle();
        bundle.putString(FirebaseAnalytics.Param.CONTENT_TYPE, screen);
        bundle.putString(FirebaseAnalytics.Param.ITEM_NAME, action);
        bundle.putString(FirebaseAnalytics.Param.ITEM_ID, action);
        firebase.logEvent(FirebaseAnalytics.Event.SELECT_CONTENT, bundle);
    }
} public class CustomIABHelper implements IabHelper.QueryInventoryFinishedListener {

    private IabHelper billingHelper;

    private static CustomIABHelper instance = null;

    private boolean isSetupDone = false;
    private boolean isPro       = false;

    private CustomIABHelper(Context context, IabHelper.QueryInventoryFinishedListener listener) {
        billingHelper = new IabHelper(context.getApplicationContext(), "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnl+N1zhaAmBhLF54yJo7T+ku8m5c/XZEsZ3+zBb7HyKCxpGuQL4+oPTVSNRtNdXNCl2R0eqojv+f3sT6tWL2XHt1DK6F7rYVtvs8rmQR1himMDEV0Tgljn5uBQuMag9nvNeyGIAi1wQeRz9Hk8tGF+laZcD3phR6NFnrwebD8FkG0lc6XHKpjAzCsdu+YbyPH7JuFAUoi+Yrbvs50r0JzeUWqz+v427V4W4kQR9zAmN3evVmou1R+2WXPtD1wGMMSQAs2DOuxfgh85o4sRS21an8xQk/d70EX3E78O3iXzl76CKZNM54O2g8iE3tkNgGfeCkqs0m2v/2E6VDubVf3QIDAQAB");

        try {
            if (!isSetupDone) {
                billingHelper.startSetup(result -> {
                    isSetupDone = true;
                    isUserPro(listener);
                });
            }
        } catch (IllegalStateException e) {
            Log.d("onResume: setup already done");
        }

    }

    public static CustomIABHelper getInstance(Context context, IabHelper.QueryInventoryFinishedListener listener) {
        if (instance == null) {
            instance = new CustomIABHelper(context, listener);
        } else {
            instance.isUserPro(listener);
        }
        return CustomIABHelper.instance;
    }

    public void isUserPro(IabHelper.QueryInventoryFinishedListener listener) {
        if (billingHelper.isSetupDone() && !billingHelper.isAsyncInProgress()) {
            try {
                billingHelper.queryInventoryAsync(false, listener);
            } catch (Exception e) {
                Log.e(e.getMessage());
            }
        }
    }

    @Override
    public void onQueryInventoryFinished(IabResult result, Inventory inv) {
        isPro = (inv.hasPurchase(SKU_UPGRADE) &&
                inv.getPurchase(SKU_UPGRADE).getPurchaseState() == Purchase.PurchaseState.PURCHASED);
    }

    public static boolean isOrderOk(IabResult result, Inventory inv) {
        return result.getResponse() == IabHelper.BILLING_RESPONSE_RESULT_OK &&
                inv.hasPurchase(SKU_UPGRADE) &&
                (inv.getPurchase(SKU_UPGRADE).getPurchaseState() == Purchase.PurchaseState.PURCHASED);
    }
} public class IabHelper {

    // Is debug logging enabled?
    boolean mDebugLog = true;
    String  mDebugTag = "SIAPv3";

    // Is setup done?
    boolean mSetupDone = false;

    // Is an asynchronous operation in progress?
    // (only one at a time can be in progress)
    boolean mAsyncInProgress = false;

    // (for logging/debugging)
    // if mAsyncInProgress == true, what asynchronous operation is in progress?
    String mAsyncOperation = "";

    // Context we were passed during initialization
    Context mContext;

    // Connection to the service
    IInAppBillingService mService;
    ServiceConnection    mServiceConn;

    // The request code used to launch purchase flow
    int mRequestCode;

    // Public key for verifying signature, in base64 encoding
    String mSignatureBase64 = null;

    // Billing response codes
    public static final int BILLING_RESPONSE_RESULT_OK                  = 0;
    public static final int BILLING_RESPONSE_RESULT_USER_CANCELED       = 1;
    public static final int BILLING_RESPONSE_RESULT_BILLING_UNAVAILABLE = 3;
    public static final int BILLING_RESPONSE_RESULT_ITEM_UNAVAILABLE    = 4;
    public static final int BILLING_RESPONSE_RESULT_DEVELOPER_ERROR     = 5;
    public static final int BILLING_RESPONSE_RESULT_ERROR               = 6;
    public static final int BILLING_RESPONSE_RESULT_ITEM_ALREADY_OWNED  = 7;
    public static final int BILLING_RESPONSE_RESULT_ITEM_NOT_OWNED      = 8;

    // IAB Helper error codes
    public static final int IABHELPER_ERROR_BASE                = -1000;
    public static final int IABHELPER_REMOTE_EXCEPTION          = -1001;
    public static final int IABHELPER_BAD_RESPONSE              = -1002;
    public static final int IABHELPER_VERIFICATION_FAILED       = -1003;
    public static final int IABHELPER_SEND_INTENT_FAILED        = -1004;
    public static final int IABHELPER_USER_CANCELLED            = -1005;
    public static final int IABHELPER_UNKNOWN_PURCHASE_RESPONSE = -1006;
    public static final int IABHELPER_MISSING_TOKEN             = -1007;
    public static final int IABHELPER_UNKNOWN_ERROR             = -1008;

    // Keys for the responses from InAppBillingService
    public static final String RESPONSE_CODE                     = "RESPONSE_CODE";
    public static final String RESPONSE_GET_SKU_DETAILS_LIST     = "DETAILS_LIST";
    public static final String RESPONSE_BUY_INTENT               = "BUY_INTENT";
    public static final String RESPONSE_INAPP_PURCHASE_DATA      = "INAPP_PURCHASE_DATA";
    public static final String RESPONSE_INAPP_SIGNATURE          = "INAPP_DATA_SIGNATURE";
    public static final String RESPONSE_INAPP_ITEM_LIST          = "INAPP_PURCHASE_ITEM_LIST";
    public static final String RESPONSE_INAPP_PURCHASE_DATA_LIST = "INAPP_PURCHASE_DATA_LIST";
    public static final String RESPONSE_INAPP_SIGNATURE_LIST     = "INAPP_DATA_SIGNATURE_LIST";
    public static final String INAPP_CONTINUATION_TOKEN          = "INAPP_CONTINUATION_TOKEN";

    // Item type: in-app item
    public static final String ITEM_TYPE_INAPP = "inapp";

    // some fields on the getSkuDetails response bundle
    public static final String GET_SKU_DETAILS_ITEM_LIST      = "ITEM_ID_LIST";
    public static final String GET_SKU_DETAILS_ITEM_TYPE_LIST = "ITEM_TYPE_LIST";

    /**
     * Creates an instance. After creation, it will not yet be ready to use. You must perform
     * setup by calling {@link #startSetup} and wait for setup to complete. This constructor does
     * not
     * block and is safe to call from a UI thread.
     *
     * @param ctx Your application or Activity context. Needed to bind to the in-app billing
     * service.
     * @param base64PublicKey Your application's public key, encoded in base64.
     * This is used for verification of purchase signatures. You can find your app's base64-encoded
     * public key in your application's page on Google Play Developer Console. Note that this
     * is NOT your "developer public key".
     */
    public IabHelper(Context ctx, String base64PublicKey) {
        mContext = ctx.getApplicationContext();
        mSignatureBase64 = base64PublicKey;
        logDebug("IAB helper created.");
    }

    /**
     * Enables or disable debug logging through LogCat.
     */
    public void enableDebugLogging(boolean enable, String tag) {
        mDebugLog = enable;
        mDebugTag = tag;
    }

    public void enableDebugLogging(boolean enable) {
        mDebugLog = enable;
    }

    /**
     * Callback for setup process. This listener's {@link #onIabSetupFinished} method is called
     * when the setup process is complete.
     */
    public interface OnIabSetupFinishedListener {

        /**
         * Called to notify that setup is complete.
         *
         * @param result The result of the setup process.
         */
        void onIabSetupFinished(IabResult result);
    }

    /**
     * Starts the setup process. This will start up the setup process asynchronously.
     * You will be notified through the listener when the setup process is complete.
     * This method is safe to call from a UI thread.
     *
     * THIS WILL NOT WORK ON an EMULATOR, YOU NEED A REAL DEVICE
     *
     * @param listener The listener to notify when the setup process is complete.
     */
    public void startSetup(final OnIabSetupFinishedListener listener) {
        // If already set up, can't do it again.
        if (mSetupDone)
            throw new IllegalStateException("IAB helper is already set up.");

        // Connection to IAB service
        logDebug("Starting in-app billing setup.");
        mServiceConn = new ServiceConnection() {

            @Override
            public void onServiceDisconnected(ComponentName name) {
                logDebug("Billing service disconnected.");
                mService = null;
            }

            @Override
            public void onServiceConnected(ComponentName name, IBinder service) {
                logDebug("Billing service connected.");
                mService = IInAppBillingService.Stub.asInterface(service);
                String packageName = mContext.getPackageName();
                try {
                    logDebug("Checking for in-app billing 3 support.");
                    int response = mService.isBillingSupported(3, packageName, ITEM_TYPE_INAPP);
                    if (response != BILLING_RESPONSE_RESULT_OK) {
                        if (listener != null) {
                            listener.onIabSetupFinished(new IabResult(response,
                                    "Error checking for billing v3 support."));
                        }
                        return;
                    }
                    logDebug("In-app billing version 3 supported for " + packageName);
                    mSetupDone = true;
                } catch (RemoteException e) {
                    if (listener != null) {
                        listener.onIabSetupFinished(new IabResult(IABHELPER_REMOTE_EXCEPTION,
                                "RemoteException while setting up in-app billing."));
                    }
                    e.printStackTrace();
                }

                if (listener != null) {
                    listener.onIabSetupFinished(new IabResult(BILLING_RESPONSE_RESULT_OK, "Setup successful."));
                }
            }
        };

        boolean attempt = mContext.getApplicationContext().bindService(new Intent("com.android.vending.billing.InAppBillingService.BIND").setPackage("com.android.vending"),
                mServiceConn, Context.BIND_AUTO_CREATE);

        if (!attempt) {
            Log.e(mDebugTag, "Failed to bind to Service with name com.android.vending.billing.InAppBillingService.BIND");
        }
    }

    /**
     * Dispose of object, releasing resources. It's very important to call this
     * method when you are done with this object. It will release any resources
     * used by it such as service connections. Naturally, once the object is
     * disposed of, it can't be used again.
     */
    public void dispose() {
        logDebug("Disposing.");
        mSetupDone = false;
        if (mServiceConn != null) {
            logDebug("Unbinding from service.");
            if (mContext != null) {
                mContext.unbindService(mServiceConn);
            }
            mServiceConn = null;
            mService = null;
            mPurchaseListener = null;
        }
    }

    /**
     * Callback that notifies when a purchase is finished.
     */
    public interface OnIabPurchaseFinishedListener {

        /**
         * Called to notify that an in-app purchase finished. If the purchase was successful,
         * then the sku parameter specifies which item was purchased. If the purchase failed,
         * the sku and extraData parameters may or may not be null, depending on how far the
         * purchase
         * process went.
         *
         * @param result The result of the purchase.
         * @param info The purchase information (null if purchase failed)
         */
        void onIabPurchaseFinished(IabResult result, Purchase info);
    }

    // The listener registered on launchPurchaseFlow, which we have to call back when
    // the purchase finishes
    OnIabPurchaseFinishedListener mPurchaseListener;

    /**
     * Same as calling {@link #launchPurchaseFlow(Activity, String, int,
     * OnIabPurchaseFinishedListener, String)} with null as
     * extraData.
     */
    public void launchPurchaseFlow(Activity act, String sku, int requestCode, OnIabPurchaseFinishedListener listener) {
        launchPurchaseFlow(act, sku, requestCode, listener, "");
    }

    /**
     * Initiate the UI flow for an in-app purchase. Call this method to initiate an in-app
     * purchase,
     * which will involve bringing up the Google Play screen. The calling activity will be paused
     * while
     * the user interacts with Google Play, and the result will be delivered via the activity's
     * {@link Activity#onActivityResult} method, at which point you must call
     * this object's {@link #handleActivityResult} method to continue the purchase flow. This
     * method
     * MUST be called from the UI thread of the Activity.
     *
     * @param act The calling activity.
     * @param sku The sku of the item to purchase.
     * @param requestCode A request code (to differentiate from other responses --
     * as in {@link Activity#startActivityForResult}).
     * @param listener The listener to notify when the purchase process finishes
     * @param extraData Extra data (developer payload), which will be returned with the purchase
     * data
     * when the purchase completes. This extra data will be permanently bound to that purchase
     * and will always be returned when the purchase is queried.
     */
    public void launchPurchaseFlow(Activity act, String sku, int requestCode, OnIabPurchaseFinishedListener listener, String extraData) {
        checkSetupDone("launchPurchaseFlow");
        flagStartAsync("launchPurchaseFlow");
        IabResult result;

        try {
            //            String purchaseToken = "inapp:" + act.getPackageName() + ":android.test.purchased";
            //            mService.consumePurchase(3, act.getPackageName(), purchaseToken);

            logDebug("Constructing buy intent for " + sku);
            Bundle buyIntentBundle = mService.getBuyIntent(3, mContext.getPackageName(), sku, ITEM_TYPE_INAPP, extraData);
            int    response        = getResponseCodeFromBundle(buyIntentBundle);
            if (response != BILLING_RESPONSE_RESULT_OK) {
                logError("Unable to buy item, Error response: " + getResponseDesc(response));

                result = new IabResult(response, "Unable to buy item");
                if (listener != null) {
                    listener.onIabPurchaseFinished(result, null);
                }
                return;
            }

            PendingIntent pendingIntent = buyIntentBundle.getParcelable(RESPONSE_BUY_INTENT);
            logDebug("Launching buy intent for " + sku + ". Request code: " + requestCode);
            mRequestCode = requestCode;
            mPurchaseListener = listener;
            act.startIntentSenderForResult(pendingIntent.getIntentSender(),
                    requestCode, new Intent(),
                    Integer.valueOf(0), Integer.valueOf(0),
                    Integer.valueOf(0));
        } catch (SendIntentException e) {
            logError("SendIntentException while launching purchase flow for sku " + sku);
            e.printStackTrace();

            result = new IabResult(IABHELPER_SEND_INTENT_FAILED, "Failed to send intent.");
            if (listener != null) {
                listener.onIabPurchaseFinished(result, null);
            }
        } catch (RemoteException e) {
            logError("RemoteException while launching purchase flow for sku " + sku);
            e.printStackTrace();

            result = new IabResult(IABHELPER_REMOTE_EXCEPTION, "Remote exception while starting purchase flow");
            if (listener != null) {
                listener.onIabPurchaseFinished(result, null);
            }
        }
    }

    /**
     * Handles an activity result that's part of the purchase flow in in-app billing. If you
     * are calling {@link #launchPurchaseFlow}, then you must call this method from your
     * Activity's {@link Activity@onActivityResult} method. This method
     * MUST be called from the UI thread of the Activity.
     *
     * @param requestCode The requestCode as you received it.
     * @param resultCode The resultCode as you received it.
     * @param data The data (Intent) as you received it.
     * @return Returns true if the result was related to a purchase flow and was handled;
     * false if the result was not related to a purchase, in which case you should
     * handle it normally.
     */
    public boolean handleActivityResult(int requestCode, int resultCode, Intent data) {
        IabResult result;
        if (requestCode != mRequestCode)
            return false;

        checkSetupDone("handleActivityResult");

        // end of async purchase operation
        flagEndAsync();

        if (data == null) {
            logError("Null data in IAB activity result.");
            result = new IabResult(IABHELPER_BAD_RESPONSE, "Null data in IAB result");
            if (mPurchaseListener != null) {
                mPurchaseListener.onIabPurchaseFinished(result, null);
            }
            return true;
        }

        int    responseCode  = getResponseCodeFromIntent(data);
        String purchaseData  = data.getStringExtra(RESPONSE_INAPP_PURCHASE_DATA);
        String dataSignature = data.getStringExtra(RESPONSE_INAPP_SIGNATURE);

        if (resultCode == Activity.RESULT_OK && responseCode == BILLING_RESPONSE_RESULT_OK) {
            logDebug("Successful resultcode from purchase activity.");
            logDebug("Purchase data: " + purchaseData);
            logDebug("Data signature: " + dataSignature);
            logDebug("Extras: " + data.getExtras());

            if (purchaseData == null || dataSignature == null) {
                logError("BUG: either purchaseData or dataSignature is null.");
                logDebug("Extras: " + data.getExtras().toString());
                result = new IabResult(IABHELPER_UNKNOWN_ERROR, "IAB returned null purchaseData or dataSignature");
                if (mPurchaseListener != null) {
                    mPurchaseListener.onIabPurchaseFinished(result, null);
                }
                return true;
            }

            Purchase purchase = null;
            try {
                purchase = new Purchase(purchaseData, dataSignature);
                String sku = purchase.getSku();

                // Verify signature
                if (!Security.verifyPurchase(mSignatureBase64, purchaseData, dataSignature)) {
                    logError("Purchase signature verification FAILED for sku " + sku);
                    result = new IabResult(IABHELPER_VERIFICATION_FAILED, "Signature verification failed for sku " + sku);
                    if (mPurchaseListener != null) {
                        mPurchaseListener.onIabPurchaseFinished(result, purchase);
                    }
                    return true;
                }
                logDebug("Purchase signature successfully verified.");
            } catch (JSONException e) {
                logError("Failed to parse purchase data.");
                e.printStackTrace();
                result = new IabResult(IABHELPER_BAD_RESPONSE, "Failed to parse purchase data.");
                if (mPurchaseListener != null) {
                    mPurchaseListener.onIabPurchaseFinished(result, null);
                }
                return true;
            }

            if (mPurchaseListener != null) {
                mPurchaseListener.onIabPurchaseFinished(new IabResult(BILLING_RESPONSE_RESULT_OK, "Success"), purchase);
            }
        } else if (resultCode == Activity.RESULT_OK) {
            // result code was OK, but in-app billing response was not OK.
            logDebug("Result code was OK but in-app billing response was not OK: " + getResponseDesc(responseCode));
            if (mPurchaseListener != null) {
                result = new IabResult(responseCode, "Problem purchashing item.");
                mPurchaseListener.onIabPurchaseFinished(result, null);
            }
        } else if (resultCode == Activity.RESULT_CANCELED) {
            logDebug("Purchase canceled - Response: " + getResponseDesc(responseCode));
            result = new IabResult(IABHELPER_USER_CANCELLED, "User canceled.");
            if (mPurchaseListener != null) {
                mPurchaseListener.onIabPurchaseFinished(result, null);
            }
        } else {
            logError("Purchase failed. Result code: " + Integer.toString(resultCode)
                    + ". Response: " + getResponseDesc(responseCode));
            result = new IabResult(IABHELPER_UNKNOWN_PURCHASE_RESPONSE, "Unknown purchase response.");
            if (mPurchaseListener != null) {
                mPurchaseListener.onIabPurchaseFinished(result, null);
            }
        }
        return true;
    }

    /**
     * Queries the inventory. This will query all owned items from the server, as well as
     * information on additional skus, if specified. This method may block or take long to execute.
     * Do not call from a UI thread. For that, use the non-blocking version
     * refreshInventoryAsync.
     *
     * @param querySkuDetails if true, SKU details (price, description, etc) will be queried as
     * well
     * as purchase information.
     * @param moreSkus additional skus to query information on, regardless of ownership. Ignored
     * if null or if querySkuDetails is false.
     * @throws IabException if a problem occurs while refreshing the inventory.
     */
    public Inventory queryInventory(boolean querySkuDetails, List<String> moreSkus) throws IabException {
        checkSetupDone("queryInventory");
        try {
            Inventory inv = new Inventory();
            int       r   = queryPurchases(inv);
            if (r != BILLING_RESPONSE_RESULT_OK)
                throw new IabException(r, "Error refreshing inventory (querying owned items).");

            if (querySkuDetails) {
                r = querySkuDetails(inv, moreSkus);
                if (r != BILLING_RESPONSE_RESULT_OK)
                    throw new IabException(r, "Error refreshing inventory (querying prices of items).");
            }
            return inv;
        } catch (RemoteException e) {
            throw new IabException(IABHELPER_REMOTE_EXCEPTION, "Remote exception while refreshing inventory.", e);
        } catch (JSONException e) {
            throw new IabException(IABHELPER_BAD_RESPONSE, "Error parsing JSON response while refreshing inventory.", e);
        }
    }

    /**
     * Listener that notifies when an inventory query operation completes.
     */
    public interface QueryInventoryFinishedListener {

        /**
         * Called to notify that an inventory query operation completed.
         *
         * @param result The result of the operation.
         * @param inv The inventory.
         */
        void onQueryInventoryFinished(IabResult result, Inventory inv);
    }

    /**
     * Asynchronous wrapper for inventory query. This will perform an inventory
     * query as described in {@link #queryInventory}, but will do so asynchronously
     * and call back the specified listener upon completion. This method is safe to
     * call from a UI thread.
     *
     * @param querySkuDetails as in {@link #queryInventory}
     * @param moreSkus as in {@link #queryInventory}
     * @param listener The listener to notify when the refresh operation completes.
     */
    public void queryInventoryAsync(final boolean querySkuDetails,
                                    final List<String> moreSkus,
                                    final QueryInventoryFinishedListener listener) {
        final Handler handler = new Handler();
        checkSetupDone("queryInventory");
        flagStartAsync("refresh inventory");
        new Thread(new Runnable() {

            @Override
            public void run() {
                IabResult result = new IabResult(BILLING_RESPONSE_RESULT_OK, "Inventory refresh successful.");
                Inventory inv    = null;
                try {
                    inv = queryInventory(querySkuDetails, moreSkus);
                } catch (IabException ex) {
                    result = ex.getResult();
                }

                flagEndAsync();

                final IabResult result_f = result;
                final Inventory inv_f    = inv;
                handler.post(new Runnable() {

                    @Override
                    public void run() {
                        listener.onQueryInventoryFinished(result_f, inv_f);
                    }
                });
            }
        }).start();
    }

    public void queryInventoryAsync(QueryInventoryFinishedListener listener) {
        queryInventoryAsync(true, null, listener);
    }

    public void queryInventoryAsync(boolean querySkuDetails, QueryInventoryFinishedListener listener) {
        queryInventoryAsync(querySkuDetails, null, listener);
    }

    /**
     * Consumes a given in-app product. Consuming can only be done on an item
     * that's owned, and as a result of consumption, the user will no longer own it.
     * This method may block or take long to return. Do not call from the UI thread.
     * For that, see {@link #consumeAsync}.
     *
     * @param itemInfo The PurchaseInfo that represents the item to consume.
     * @throws IabException if there is a problem during consumption.
     */
    void consume(Purchase itemInfo) throws IabException {
        checkSetupDone("consume");
        try {
            String token = itemInfo.getToken();
            String sku   = itemInfo.getSku();
            if (token == null || token.equals("")) {
                logError("Can't consume " + sku + ". No token.");
                throw new IabException(IABHELPER_MISSING_TOKEN, "PurchaseInfo is missing token for sku: "
                        + sku + " " + itemInfo);
            }

            logDebug("Consuming sku: " + sku + ", token: " + token);
            int response = mService.consumePurchase(3, mContext.getPackageName(), token);
            if (response == BILLING_RESPONSE_RESULT_OK) {
                logDebug("Successfully consumed sku: " + sku);
            } else {
                logDebug("Error consuming consuming sku " + sku + ". " + getResponseDesc(response));
                throw new IabException(response, "Error consuming sku " + sku);
            }
        } catch (RemoteException e) {
            throw new IabException(IABHELPER_REMOTE_EXCEPTION, "Remote exception while consuming. PurchaseInfo: " + itemInfo, e);
        } catch (NullPointerException e) {
            Log.d("consume: ", e.getMessage());
        }
    }

    /**
     * Callback that notifies when a consumption operation finishes.
     */
    public interface OnConsumeFinishedListener {

        /**
         * Called to notify that a consumption has finished.
         *
         * @param purchase The purchase that was (or was to be) consumed.
         * @param result The result of the consumption operation.
         */
        void onConsumeFinished(Purchase purchase, IabResult result);
    }

    /**
     * Callback that notifies when a multi-item consumption operation finishes.
     */
    public interface OnConsumeMultiFinishedListener {

        /**
         * Called to notify that a consumption of multiple items has finished.
         *
         * @param purchases The purchases that were (or were to be) consumed.
         * @param results The results of each consumption operation, corresponding to each
         * sku.
         */
        void onConsumeMultiFinished(List<Purchase> purchases, List<IabResult> results);
    }

    /**
     * Asynchronous wrapper to item consumption. Works like {@link #consume}, but
     * performs the consumption in the background and notifies completion through
     * the provided listener. This method is safe to call from a UI thread.
     *
     * @param purchase The purchase to be consumed.
     * @param listener The listener to notify when the consumption operation finishes.
     */
    public void consumeAsync(Purchase purchase, OnConsumeFinishedListener listener) {
        checkSetupDone("consume");
        List<Purchase> purchases = new ArrayList<Purchase>();
        purchases.add(purchase);
        consumeAsyncInternal(purchases, listener, null);
    }

    /**
     * Same as consumeAsync, but for multiple items at once.
     *
     * @param purchases The list of PurchaseInfo objects representing the purchases to consume.
     * @param listener The listener to notify when the consumption operation finishes.
     */
    public void consumeAsync(List<Purchase> purchases, OnConsumeMultiFinishedListener listener) {
        checkSetupDone("consume");
        consumeAsyncInternal(purchases, null, listener);
    }

    /**
     * Returns a human-readable description for the given response code.
     *
     * @param code The response code
     * @return A human-readable string explaining the result code.
     * It also includes the result code numerically.
     */
    public static String getResponseDesc(int code) {
        String[] iab_msgs = ("0:OK/1:User Canceled/2:Unknown/" +
                "3:Billing Unavailable/4:Item unavailable/" +
                "5:Developer Error/6:Error/7:Item Already Owned/" +
                "8:Item not owned").split("/");
        String[] iabhelper_msgs = ("0:OK/-1001:Remote exception during initialization/" +
                "-1002:Bad response received/" +
                "-1003:Purchase signature verification failed/" +
                "-1004:Send intent failed/" +
                "-1005:User cancelled/" +
                "-1006:Unknown purchase response/" +
                "-1007:Missing token/" +
                "-1008:Unknown error").split("/");

        if (code <= IABHELPER_ERROR_BASE) {
            int index = IABHELPER_ERROR_BASE - code;
            if (index >= 0 && index < iabhelper_msgs.length)
                return iabhelper_msgs[index];
            else
                return String.valueOf(code) + ":Unknown IAB Helper Error";
        } else if (code < 0 || code >= iab_msgs.length)
            return String.valueOf(code) + ":Unknown";
        else
            return iab_msgs[code];
    }

    // Checks that setup was done; if not, throws an exception.
    void checkSetupDone(String operation) {
        if (!mSetupDone) {
            logError("Illegal state for operation (" + operation + "): IAB helper is not set up.");
            throw new IllegalStateException("IAB helper is not set up. Can't perform operation: " + operation);
        }
    }

    // Workaround to bug where sometimes response codes come as Long instead of Integer
    int getResponseCodeFromBundle(Bundle b) {
        Object o = b.get(RESPONSE_CODE);
        if (o == null) {
            logDebug("Bundle with null response code, assuming OK (known issue)");
            return BILLING_RESPONSE_RESULT_OK;
        } else if (o instanceof Integer)
            return ((Integer) o).intValue();
        else if (o instanceof Long)
            return (int) ((Long) o).longValue();
        else {
            logError("Unexpected type for bundle response code.");
            logError(o.getClass().getName());
            throw new RuntimeException("Unexpected type for bundle response code: " + o.getClass().getName());
        }
    }

    // Workaround to bug where sometimes response codes come as Long instead of Integer
    int getResponseCodeFromIntent(Intent i) {
        Object o = i.getExtras().get(RESPONSE_CODE);
        if (o == null) {
            logError("Intent with no response code, assuming OK (known issue)");
            return BILLING_RESPONSE_RESULT_OK;
        } else if (o instanceof Integer)
            return ((Integer) o).intValue();
        else if (o instanceof Long)
            return (int) ((Long) o).longValue();
        else {
            logError("Unexpected type for intent response code.");
            logError(o.getClass().getName());
            throw new RuntimeException("Unexpected type for intent response code: " + o.getClass().getName());
        }
    }

    void flagStartAsync(String operation) {
        if (mAsyncInProgress) {
            throw new IllegalStateException("Can't start async operation (" +
                    operation + ") because another async operation(" + mAsyncOperation + ") is in progress.");
        } else {
            mAsyncOperation = operation;
            mAsyncInProgress = true;
            logDebug("Starting async operation: " + operation);
        }
    }

    public void flagEndAsync() {
        logDebug("Ending async operation: " + mAsyncOperation);
        mAsyncOperation = "";
        mAsyncInProgress = false;
    }

    int queryPurchases(Inventory inv) throws JSONException, RemoteException {
        // Query purchases
        logDebug("Querying owned items...");
        logDebug("Package name: " + mContext.getPackageName());
        boolean verificationFailed = false;
        String  continueToken      = null;

        do {
            logDebug("Calling getPurchases with continuation token: " + continueToken);
            if (mService == null || mContext == null) {
                logError("Our service and/or our context are null.  Exiting.");
                return IABHELPER_UNKNOWN_ERROR;
            }
            Bundle ownedItems = mService.getPurchases(3, mContext.getPackageName(),
                    ITEM_TYPE_INAPP, continueToken);

            int response = getResponseCodeFromBundle(ownedItems);
            logDebug("Owned items response: " + String.valueOf(response));
            if (response != BILLING_RESPONSE_RESULT_OK) {
                logDebug("getPurchases() failed: " + getResponseDesc(response));
                return response;
            }
            if (!ownedItems.containsKey(RESPONSE_INAPP_ITEM_LIST)
                    || !ownedItems.containsKey(RESPONSE_INAPP_PURCHASE_DATA_LIST)
                    || !ownedItems.containsKey(RESPONSE_INAPP_SIGNATURE_LIST)) {
                logError("Bundle returned from getPurchases() doesn't contain required fields.");
                return IABHELPER_BAD_RESPONSE;
            }

            ArrayList<String> ownedSkus = ownedItems.getStringArrayList(
                    RESPONSE_INAPP_ITEM_LIST);
            ArrayList<String> purchaseDataList = ownedItems.getStringArrayList(
                    RESPONSE_INAPP_PURCHASE_DATA_LIST);
            ArrayList<String> signatureList = ownedItems.getStringArrayList(
                    RESPONSE_INAPP_SIGNATURE_LIST);

            for (int i = 0; i < purchaseDataList.size(); ++i) {
                String purchaseData = purchaseDataList.get(i);
                String signature    = signatureList.get(i);
                String sku          = ownedSkus.get(i);
                if (Security.verifyPurchase(mSignatureBase64, purchaseData, signature)) {
                    logDebug("Sku is owned: " + sku);
                    Purchase purchase = new Purchase(purchaseData, signature);

                    if (TextUtils.isEmpty(purchase.getToken())) {
                        logWarn("BUG: empty/null token!");
                        logDebug("Purchase data: " + purchaseData);
                    }

                    // Record ownership and token
                    inv.addPurchase(purchase);
                } else {
                    logWarn("Purchase signature verification **FAILED**. Not adding item.");
                    logDebug("   Purchase data: " + purchaseData);
                    logDebug("   Signature: " + signature);
                    verificationFailed = true;
                }
            }

            continueToken = ownedItems.getString(INAPP_CONTINUATION_TOKEN);
            logDebug("Continuation token: " + continueToken);
        } while (!TextUtils.isEmpty(continueToken));

        return verificationFailed ? IABHELPER_VERIFICATION_FAILED : BILLING_RESPONSE_RESULT_OK;
    }

    int querySkuDetails(Inventory inv, List<String> moreSkus) throws RemoteException, JSONException {
        logDebug("Querying SKU details.");
        ArrayList<String> skuList = new ArrayList<String>();
        skuList.addAll(inv.getAllOwnedSkus());
        if (moreSkus != null) {
            skuList.addAll(moreSkus);
        }

        if (skuList.size() == 0) {
            logDebug("queryPrices: nothing to do because there are no SKUs.");
            return BILLING_RESPONSE_RESULT_OK;
        }

        Bundle querySkus = new Bundle();
        querySkus.putStringArrayList(GET_SKU_DETAILS_ITEM_LIST, skuList);
        Bundle skuDetails = mService.getSkuDetails(3, mContext.getPackageName(),
                ITEM_TYPE_INAPP, querySkus);

        if (!skuDetails.containsKey(RESPONSE_GET_SKU_DETAILS_LIST)) {
            int response = getResponseCodeFromBundle(skuDetails);
            if (response != BILLING_RESPONSE_RESULT_OK) {
                logDebug("getSkuDetails() failed: " + getResponseDesc(response));
                return response;
            } else {
                logError("getSkuDetails() returned a bundle with neither an error nor a detail list.");
                return IABHELPER_BAD_RESPONSE;
            }
        }

        ArrayList<String> responseList = skuDetails.getStringArrayList(
                RESPONSE_GET_SKU_DETAILS_LIST);

        for (String thisResponse : responseList) {
            SkuDetails d = new SkuDetails(thisResponse);
            logDebug("Got sku details: " + d);
            inv.addSkuDetails(d);
        }
        return BILLING_RESPONSE_RESULT_OK;
    }

    void consumeAsyncInternal(final List<Purchase> purchases,
                              final OnConsumeFinishedListener singleListener,
                              final OnConsumeMultiFinishedListener multiListener) {
        final Handler handler = new Handler();
        flagStartAsync("consume");
        new Thread(new Runnable() {

            @Override
            public void run() {
                final List<IabResult> results = new ArrayList<IabResult>();
                for (Purchase purchase : purchases) {
                    try {
                        consume(purchase);
                        results.add(new IabResult(BILLING_RESPONSE_RESULT_OK, "Successful consume of sku " + purchase.getSku()));
                    } catch (IabException ex) {
                        results.add(ex.getResult());
                    }
                }

                flagEndAsync();
                if (singleListener != null) {
                    handler.post(new Runnable() {

                        @Override
                        public void run() {
                            singleListener.onConsumeFinished(purchases.get(0), results.get(0));
                        }
                    });
                }
                if (multiListener != null) {
                    handler.post(new Runnable() {

                        @Override
                        public void run() {
                            multiListener.onConsumeMultiFinished(purchases, results);
                        }
                    });
                }
            }
        }).start();
    }

    public boolean isAsyncInProgress() {
        return mAsyncInProgress;
    }

    public boolean isSetupDone() {
        return mSetupDone;
    }

    void logDebug(String msg) {
        if (mDebugLog) {
            Log.d(mDebugTag, msg);
        }
    }

    void logError(String msg) {
        FirebaseCrash.report(new Exception("In-app billing error: " + msg));
        Log.e(mDebugTag, "In-app billing error: " + msg);
    }

    void logWarn(String msg) {
        Log.w(mDebugTag, "In-app billing warning: " + msg);
    }
} public class IabResult {

    int    mResponse;
    String mMessage;

    public IabResult(int response, String message) {
        mResponse = response;
        if (message == null || message.trim().length() == 0) {
            mMessage = IabHelper.getResponseDesc(response);
        } else {
            mMessage = message + " (response: " + IabHelper.getResponseDesc(response) + ")";
        }
    }

    public int getResponse() {
        return mResponse;
    }

    public String getMessage() {
        return mMessage;
    }

    public boolean isSuccess() {
        return mResponse == IabHelper.BILLING_RESPONSE_RESULT_OK;
    }

    public boolean isFailure() {
        return !isSuccess();
    }

    @Override
    public String toString() {
        return "IabResult: " + getMessage();
    }
} public class Purchase {

    String mOrderId;
    String mPackageName;
    String mSku;
    long   mPurchaseTime;
    int    mPurchaseState;
    String mDeveloperPayload;
    String mToken;
    String mOriginalJson;
    String mSignature;

    public Purchase(String jsonPurchaseInfo, String signature) throws JSONException {
        mOriginalJson = jsonPurchaseInfo;
        JSONObject o = new JSONObject(mOriginalJson);
        mOrderId = o.optString("orderId");
        mPackageName = o.optString("packageName");
        mSku = o.optString("productId");
        mPurchaseTime = o.optLong("purchaseTime");
        mPurchaseState = o.optInt("purchaseState");
        mDeveloperPayload = o.optString("developerPayload");
        mToken = o.optString("token", o.optString("purchaseToken"));
        mSignature = signature;
    }

    public String getOrderId() {
        return mOrderId;
    }

    public String getPackageName() {
        return mPackageName;
    }

    public String getSku() {
        return mSku;
    }

    public long getPurchaseTime() {
        return mPurchaseTime;
    }

    public int getPurchaseState() {
        return mPurchaseState;
    }

    public String getDeveloperPayload() {
        return mDeveloperPayload;
    }

    public String getToken() {
        return mToken;
    }

    public String getOriginalJson() {
        return mOriginalJson;
    }

    public String getSignature() {
        return mSignature;
    }

    @Override
    public String toString() {
        return "PurchaseInfo:" + mOriginalJson;
    }
} public class ProPreferences {

    public static void enableAllPro(Context context) {
        ProPreferences.enablePro(context);
        ProPreferences.enableLiveNotification(context);
        ProPreferences.enableInstantDelay(context);
        ProPreferences.enableCompactNotification(context);
        ProPreferences.enableAutoRemoveNotification(context);
    }

    public static void disableAllPro(Context context) {
        ProPreferences.disablePro(context);
        ProPreferences.disableLiveNotification(context);
        ProPreferences.disableInstantDelay(context);
        ProPreferences.disableCompactNotification(context);
        ProPreferences.disableAutoRemoveNotification(context);
    }

    // instant delay
    public static boolean isPro(Context context) {
        return SharedPreferencesHelper.getSharedPreferenceBoolean(context, SP_SP_IS_PRO, false);
    }

    public static void enablePro(Context context) {
        enableGenericSetting(context, SP_SP_IS_PRO);
    }

    public static void disablePro(Context context) {
        disableGenericSetting(context, SP_SP_IS_PRO);
    }

    // instant delay
    public static boolean isInstantDelayEnabled(Context context) {
        return SharedPreferencesHelper.getSharedPreferenceBoolean(context, SP_SETT_INSTANT_DELAY, true);
    }

    public static void enableInstantDelay(Context context) {
        enableGenericSetting(context, SP_SETT_INSTANT_DELAY);
    }

    public static void disableInstantDelay(Context context) {
        disableGenericSetting(context, SP_SETT_INSTANT_DELAY);
    }

    // live notification
    public static boolean isLiveNotificationEnabled(Context context) {
        return SharedPreferencesHelper.getSharedPreferenceBoolean(context, SP_SETT_NOTIF_LIVE, true);
    }

    public static void enableLiveNotification(Context context) {
        enableGenericSetting(context, SP_SETT_NOTIF_LIVE);
    }

    public static void disableLiveNotification(Context context) {
        disableGenericSetting(context, SP_SETT_NOTIF_LIVE);
    }

    // live notification
    public static boolean isCompactNotificationEnabled(Context context) {
        return SharedPreferencesHelper.getSharedPreferenceBoolean(context, SP_SETT_NOTIF_COMPACT, true);
    }

    public static void enableCompactNotification(Context context) {
        enableGenericSetting(context, SP_SETT_NOTIF_COMPACT);
    }

    public static void disableCompactNotification(Context context) {
        disableGenericSetting(context, SP_SETT_NOTIF_COMPACT);
    }

    // auto removing notification
    public static boolean isAutoRemoveNotificationEnabled(Context context) {
        return SharedPreferencesHelper.getSharedPreferenceBoolean(context, SP_SETT_NOTIF_AUTO_REMOVE, true);
    }

    public static void enableAutoRemoveNotification(Context context) {
        enableGenericSetting(context, SP_SETT_NOTIF_AUTO_REMOVE);
    }

    public static void disableAutoRemoveNotification(Context context) {
        disableGenericSetting(context, SP_SETT_NOTIF_AUTO_REMOVE);
    }

} public static final ButterKnife.Action<View> GONE = (view, index) -> view.setVisibility(View.GONE); public static final ButterKnife.Action<View> VISIBLE = (view, index) -> view.setVisibility(View.VISIBLE); public static final String IAP_BOTTOM        = "IAP tap button bottom"; public static final String IAP_PAYPAL        = "IAP tap button paypal"; public static final String IAP_TOP           = "IAP tap button top"; public static final String SCREEN_UPGRADE_LICENSE    = "UPGR"; public static final String FIREBASE_IAP_BTN_MESSAGE          = "iap_btn_message"; public static final String FIREBASE_PRO_USERS_NUMBER         = "pro_users"; public static final String FIREBASE_SHOW_MONEY_IN_IAP        = "show_money_in_iap";
import com.google.firebase.crash.FirebaseCrash;
import com.google.firebase.remoteconfig.FirebaseRemoteConfig;
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
import android.net.Uri;
import android.os.Bundle;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.LayoutInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import com.jaus.albertogiunta.justintrain_oraritreni.BuildConfig;
import com.jaus.albertogiunta.justintrain_oraritreni.R;
import com.jaus.albertogiunta.justintrain_oraritreni.utils.helpers.AnalyticsHelper;
import com.jaus.albertogiunta.justintrain_oraritreni.utils.helpers.CustomIABHelper;
import com.jaus.albertogiunta.justintrain_oraritreni.utils.helpers.IAB.IabHelper;
import com.jaus.albertogiunta.justintrain_oraritreni.utils.helpers.IAB.IabResult;
import com.jaus.albertogiunta.justintrain_oraritreni.utils.helpers.IAB.Purchase;
import com.jaus.albertogiunta.justintrain_oraritreni.utils.sharedPreferences.ProPreferences;
import uk.co.chrisjenx.calligraphy.CalligraphyContextWrapper;
import java.util.LinkedList;
import java.util.List;
import butterknife.BindView;
import butterknife.BindViews;
import butterknife.ButterKnife;
import trikita.log.Log;
import static butterknife.ButterKnife.apply;
import static com.jaus.albertogiunta.justintrain_oraritreni.utils.components.ViewsUtils.GONE;
import static com.jaus.albertogiunta.justintrain_oraritreni.utils.components.ViewsUtils.VISIBLE;
import static com.jaus.albertogiunta.justintrain_oraritreni.utils.constants.CONST_ANALYTICS.IAP_BOTTOM;
import static com.jaus.albertogiunta.justintrain_oraritreni.utils.constants.CONST_ANALYTICS.IAP_PAYPAL;
import static com.jaus.albertogiunta.justintrain_oraritreni.utils.constants.CONST_ANALYTICS.IAP_TOP;
import static com.jaus.albertogiunta.justintrain_oraritreni.utils.constants.CONST_ANALYTICS.SCREEN_UPGRADE_LICENSE;
import static com.jaus.albertogiunta.justintrain_oraritreni.utils.constants.CONST_FIREBASE.FIREBASE_IAP_BTN_MESSAGE;
import static com.jaus.albertogiunta.justintrain_oraritreni.utils.constants.CONST_FIREBASE.FIREBASE_PRO_USERS_NUMBER;
import static com.jaus.albertogiunta.justintrain_oraritreni.utils.constants.CONST_FIREBASE.FIREBASE_SHOW_MONEY_IN_IAP;
package com.jaus.albertogiunta.justintrain_oraritreni.aboutAndSettings;








//public class LicenseUpgradeActivity extends AppCompatActivity implements PurchasesUpdatedListener {
public class LicenseUpgradeActivity extends AppCompatActivity implements IabHelper.OnIabSetupFinishedListener, IabHelper.OnIabPurchaseFinishedListener {

    AnalyticsHelper analyticsHelper;

    public static final String SKU_UPGRADE  = "premium_upgrade_mp";
    public static final String SKU_DONATION = "donate";

    @BindView(R.id.toolbar)
    Toolbar  toolbar;
    @BindView(R.id.btn_iap_first)
    Button   btnBuyFirst;
    @BindView(R.id.btn_iap_second)
    Button   btnBuySecond;
    @BindView(R.id.tv_already_pro)
    TextView tvAlreadyPro;
    @BindView(R.id.btn_donate_paypal)
    Button   btnAlreadyProPaypal;
    @BindView(R.id.tv_pro_users_number)
    TextView tvProUsersNumber;

    @BindViews({R.id.tv_already_pro, R.id.ll_already_pro_for_paypal})
    List<View> alreadyProViews = new LinkedList<>();

    boolean isAlreadyPro = false;
    private IabHelper billingHelper;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_license_upgrade);
        ButterKnife.bind(this);
        analyticsHelper = AnalyticsHelper.getInstance(LicenseUpgradeActivity.this);

        setSupportActionBar(toolbar);
        if (getSupportActionBar() != null) {
            getSupportActionBar().setDisplayHomeAsUpEnabled(true);
        }

        billingHelper = new IabHelper(this, "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnl+N1zhaAmBhLF54yJo7T+ku8m5c/XZEsZ3+zBb7HyKCxpGuQL4+oPTVSNRtNdXNCl2R0eqojv+f3sT6tWL2XHt1DK6F7rYVtvs8rmQR1himMDEV0Tgljn5uBQuMag9nvNeyGIAi1wQeRz9Hk8tGF+laZcD3phR6NFnrwebD8FkG0lc6XHKpjAzCsdu+YbyPH7JuFAUoi+Yrbvs50r0JzeUWqz+v427V4W4kQR9zAmN3evVmou1R+2WXPtD1wGMMSQAs2DOuxfgh85o4sRS21an8xQk/d70EX3E78O3iXzl76CKZNM54O2g8iE3tkNgGfeCkqs0m2v/2E6VDubVf3QIDAQAB");
        billingHelper.startSetup(this);

        btnBuyFirst.setOnClickListener(v -> {
            onIAPButtonClicked();
            analyticsHelper.logScreenEvent(SCREEN_UPGRADE_LICENSE, IAP_TOP);
        });

        btnBuySecond.setOnClickListener(v -> {
            onIAPButtonClicked();
            analyticsHelper.logScreenEvent(SCREEN_UPGRADE_LICENSE, IAP_BOTTOM);
        });

        btnAlreadyProPaypal.setOnClickListener(v -> {
            Uri    uri    = Uri.parse("https://www.paypal.me/albertogiunta");
            Intent intent = new Intent(Intent.ACTION_VIEW, uri);
            startActivity(intent);
            analyticsHelper.logScreenEvent(SCREEN_UPGRADE_LICENSE, IAP_PAYPAL);
        });

        Resources res          = getResources();
        String    proUsrNumber = String.format(res.getString(R.string.upgrade_pro_users_number), ((int) FirebaseRemoteConfig.getInstance().getDouble(FIREBASE_PRO_USERS_NUMBER)));
        tvProUsersNumber.setText(proUsrNumber);

    }

    @Override
    protected void attachBaseContext(Context newBase) {
        super.attachBaseContext(CalligraphyContextWrapper.wrap(newBase));
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            // Respond to the action bar's Up/Home button
            case android.R.id.home:
                finish();
                return true;
        }
        return super.onOptionsItemSelected(item);
    }

    public void onIAPButtonClicked() {
        if (isAlreadyPro) {
            purchaseItem(SKU_DONATION);
        } else {
            purchaseItem(SKU_UPGRADE);
        }
    }

    @Override
    public void onIabSetupFinished(IabResult result) {
        if (result.isSuccess()) {
            dealWithIabSetupSuccess(result);
        } else {
            Log.d("Problem setting up In-app Billing: " + result);
            dealWithIabSetupFailure();
        }
    }

    private void dealWithIabSetupSuccess(IabResult result) {
        List<String> l = new LinkedList<>();
        l.add(SKU_UPGRADE);
        l.add(SKU_DONATION);
        if (billingHelper.isSetupDone() && !billingHelper.isAsyncInProgress()) {
            billingHelper.queryInventoryAsync(true, l, (result2, inv) -> {
                if (inv != null && inv.getSkuDetails(SKU_UPGRADE) != null) {
                    if (CustomIABHelper.isOrderOk(result2, inv)) {
                        isAlreadyPro = true;
                        apply(alreadyProViews, VISIBLE);
                        String textForBtn = "SUPPORTA LO SVILUPPO";
                        if (FirebaseRemoteConfig.getInstance().getBoolean(FIREBASE_SHOW_MONEY_IN_IAP)) {