class FontsContractCompat {

    @RestrictTo(LIBRARY_GROUP)
    public static Typeface getFontSync(final Context context, final FontRequest request,
            final @Nullable ResourcesCompat.FontCallback fontCallback,
            final @Nullable Handler handler, boolean isBlockingFetch, int timeout,
            final int style) {
        final String id = request.getIdentifier() + "-" + style;
        Typeface cached = sTypefaceCache.get(id);
        if (cached != null) {
            if (fontCallback != null) {
                fontCallback.onFontRetrieved(cached);
            }
            return cached;
        }

        if (isBlockingFetch && timeout == FontResourcesParserCompat.INFINITE_TIMEOUT_VALUE) {
            // Wait forever. No need to post to the thread.
            TypefaceResult typefaceResult = getFontInternal(context, request, style);
            if (fontCallback != null) {
                if (typefaceResult.mResult == FontFamilyResult.STATUS_OK) {
                    fontCallback.callbackSuccessAsync(typefaceResult.mTypeface, handler);
                } else {
                    fontCallback.callbackFailAsync(typefaceResult.mResult, handler);
                }
            }
            return typefaceResult.mTypeface;
        }

        final Callable<TypefaceResult> fetcher = new Callable<TypefaceResult>() {
            @Override
            public TypefaceResult call() throws Exception {
                TypefaceResult typeface = getFontInternal(context, request, style);
                if (typeface.mTypeface != null) {
                    sTypefaceCache.put(id, typeface.mTypeface);
                }
                return typeface;
            }
        };

        if (isBlockingFetch) {
            try {
                return sBackgroundThread.postAndWait(fetcher, timeout).mTypeface;
            } catch (InterruptedException e) {
                return null;
            }
        } else {
            final ReplyCallback<TypefaceResult> reply = fontCallback == null ? null
                    : new ReplyCallback<TypefaceResult>() {
                        @Override
                        public void onReply(final TypefaceResult typeface) {
                            if (typeface == null) {
                                fontCallback.callbackFailAsync(
                                        FontRequestCallback.FAIL_REASON_FONT_NOT_FOUND, handler);
                            } else if (typeface.mResult == FontFamilyResult.STATUS_OK) {
                                fontCallback.callbackSuccessAsync(typeface.mTypeface, handler);
                            } else {
                                fontCallback.callbackFailAsync(typeface.mResult, handler);
                            }
                        }
                    };

            synchronized (sLock) {
                if (sPendingReplies.containsKey(id)) {
                    // Already requested. Do not request the same provider again and insert the
                    // reply to the queue instead.
                    if (reply != null) {
                        sPendingReplies.get(id).add(reply);
                    }
                    return null;
                }
                if (reply != null) {
                    ArrayList<ReplyCallback<TypefaceResult>> pendingReplies = new ArrayList<>();
                    pendingReplies.add(reply);
                    sPendingReplies.put(id, pendingReplies);
                }
            }
            sBackgroundThread.postAndReply(fetcher, new ReplyCallback<TypefaceResult>() {
                @Override
                public void onReply(final TypefaceResult typeface) {
                    final ArrayList<ReplyCallback<TypefaceResult>> replies;
                    synchronized (sLock) {
                        replies = sPendingReplies.get(id);
                        if (replies == null) {
                            return;  // Nobody requested replies. Do nothing.
                        }
                        sPendingReplies.remove(id);
                    }
                    for (int i = 0; i < replies.size(); ++i) {
                        replies.get(i).onReply(typeface);
                    }
                }
            });
            return null;
        }
    }

    private  FontsContractCompat();

}