// Copyright 2020 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package com.google.androidbrowserhelper.playbilling.digitalgoods;

import com.android.billingclient.api.BillingClient;
import com.android.billingclient.api.BillingClient.SkuType;
import com.android.billingclient.api.BillingResult;
import com.android.billingclient.api.SkuDetails;
import com.android.billingclient.api.SkuDetailsResponseListener;

import java.util.ArrayList;
import java.util.List;

import androidx.annotation.Nullable;

/**
 * Play Billing SKUs are split into purchases and subscriptions. This isn't a distinction that
 * exists in the Digital Goods API, but since SKU ids are unique across both product types, we can
 * just call methods that take a skuType twice, once with {@link SkuType#INAPP} and once with
 * {@link SkuType#SUBS}. This class exists to combine the results of those calls.
 *
 * Although the Play Billing methods are asynchronous, their callbacks (which will call
 * {@link #setInAppResult} and {@link #setSubsResult}) should both take place on the UI thread, so
 * we don't need to worry about any concurrency.
 */
public class BillingResultMerger<T> {
    private final ResultListener<T> mOnCombinedResult;

    private @Nullable BillingResult mInAppResult;
    private @Nullable List<T> mInAppDetailsList;
    private @Nullable BillingResult mSubsResult;
    private @Nullable List<T> mSubsDetailsList;

    public interface ResultListener<T> {
        void onResult(BillingResult responseCode, List<T> combinedResult);
    }

    public BillingResultMerger(ResultListener<T> onCombinedResult) {
        mOnCombinedResult = onCombinedResult;
    }

    public void setInAppResult(BillingResult result, @Nullable List<T> detailsList) {
        mInAppResult = result;
        mInAppDetailsList = detailsList;

        triggerIfReady();
    }

    public void setSubsResult(BillingResult result, @Nullable List<T> detailsList) {
        mSubsResult = result;
        mSubsDetailsList = detailsList;

        triggerIfReady();
    }

    private void triggerIfReady() {
        if (mSubsResult == null || mInAppResult == null) return;

        BillingResult result;
        @Nullable List<T> detailsList;
        if (mSubsDetailsList == null || mSubsDetailsList.isEmpty()) {
            // If one of the lists is null or empty, just use the results from the other call.
            result = mInAppResult;
            detailsList = mInAppDetailsList;
        } else if (mInAppDetailsList == null || mInAppDetailsList.isEmpty()) {
            result = mSubsResult;
            detailsList = mSubsDetailsList;
        } else {
            // To merge the BillingResult:
            // - If one call failed, pick that.
            // - Arbitrarily return the INAPP result otherwise.
            if (didSucceed(mInAppResult) && !didSucceed(mSubsResult)) {
                result = mSubsResult;
            } else {
                result = mInAppResult;
            }

            // To merge the lists, we just combine them.
            // Since we're in this branch, we know the two lists are non-null and non-empty.
            detailsList = new ArrayList<>(mInAppDetailsList);
            detailsList.addAll(mSubsDetailsList);
        }

        mOnCombinedResult.onResult(result, detailsList);
    }

    private static boolean didSucceed(BillingResult result) {
        return result.getResponseCode() == BillingClient.BillingResponseCode.OK;
    }
}

@@ -837,122 +837,8 @@
 ult;
-%0Aimport com.android.billingclient.api.SkuDetails;%0Aimport com.android.billingclient.api.SkuDetailsResponseListener;
 %0A%0Aim
@@ -1718,30 +1718,30 @@
 st%3CT%3E mInApp
-Detail
+Result
 sList;%0A    p
@@ -1815,30 +1815,30 @@
 ist%3CT%3E mSubs
-Detail
+Result
 sList;%0A%0A    
@@ -2141,38 +2141,38 @@
 ullable List%3CT%3E 
-detail
+result
 sList) %7B%0A       
@@ -2209,30 +2209,30 @@
   mInApp
-Detail
+Result
 sList = 
 detailsL
@@ -2215,38 +2215,38 @@
 ppResultsList = 
-detail
+result
 sList;%0A%0A        
@@ -2336,30 +2336,30 @@
 ble List%3CT%3E 
-detail
+result
 sList) %7B%0A   
@@ -2402,22 +2402,22 @@
 Subs
-Detail
+Result
 sList = 
 deta
@@ -2412,22 +2412,22 @@
 sList = 
-detail
+result
 sList;%0A%0A
@@ -2643,30 +2643,30 @@
    if (mSubs
-Detail
+Result
 sList == nul
@@ -2671,30 +2671,30 @@
 ull %7C%7C mSubs
-Detail
+Result
 sList.isEmpt
@@ -2858,30 +2858,30 @@
 ist = mInApp
-Detail
+Result
 sList;%0A     
@@ -2896,30 +2896,30 @@
 e if (mInApp
-Detail
+Result
 sList == nul
@@ -2925,30 +2925,30 @@
 ll %7C%7C mInApp
-Detail
+Result
 sList.isEmpt
@@ -3015,30 +3015,30 @@
 List = mSubs
-Detail
+Result
 sList;%0A     
@@ -3587,22 +3587,22 @@
 %3E(mInApp
-Detail
+Result
 sList);%0A
@@ -3641,14 +3641,14 @@
 Subs
-Detail
+Result
 sLis

Rename lists.