package com.avg.zaap.crashlibrary;

import android.support.annotation.NonNull;
import android.support.annotation.Nullable;

import com.avg.zaap.crashlibrary.core.logger.CrashLogger;
import com.avg.zaap.crashlibrary.provider.ICrashProviderCallback;

/**
 * This class handles the asynchronous provider's callbacks and calls for publishing data when
 * all of them has responded.
 * <p>
 * Created by marek.osvald on 4.5.2016.
 */
public class CrashPublisherCallbackHandler implements ICrashProviderCallback {

    private static final String TAG = CrashPublisherCallbackHandler.class.getSimpleName();

    private ReportData mReportData;
    private int mAsyncProviderCount;
    private int mCalledProvidersCount;
    private ICrashReporterCallback mCallback;
    private final Object mLock = new Object();

    /**
     * Parametric constructor. Sets synchronous provider file paths to add the asynchronous results
     * to, total asynchronous provider count and callback to the crash reporter.
     *
     * @param reportData report data structure
     * @param callback   callback to call when all asynchronous providers has finished
     */
    public CrashPublisherCallbackHandler(@NonNull ReportData reportData, @NonNull ICrashReporterCallback callback) {
        mReportData = reportData;
        mAsyncProviderCount = CrashLib.getConfig().getAsyncProviders().size();
        mCallback = callback;
    }

    @Override
    public void onSuccess(@NonNull final String filepath) {
        CrashLogger.d(TAG, "Async provider provided data to %s.", filepath);

        //add path to files for packing
        synchronized (mLock) {
            mReportData.getFilesToPack().add(filepath);
            if (++mCalledProvidersCount == mAsyncProviderCount) {
                mCallback.publishResults(mReportData);
            }
        }
    }

    @Override
    public void onFailure(@NonNull String providerName, @Nullable Throwable throwable) {
        CrashLogger.e(TAG, "Async provider %s failed to provide data: %s", providerName, throwable != null ? throwable.getMessage() : "null");

        synchronized (mLock) {
            if (++mCalledProvidersCount == mAsyncProviderCount) {
                mCallback.publishResults(mReportData);
            }
        }
    }

}
