/*
 * Copyright (C) 2019 The Android Open Source Project
 *
 * 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.android.car.setupwizardlib;

import android.animation.ValueAnimator;
import android.annotation.Nullable;
import android.content.Context;
import android.content.res.ColorStateList;
import android.content.res.TypedArray;
import android.graphics.PorterDuff;
import android.graphics.Rect;
import android.graphics.Typeface;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.GradientDrawable;
import android.graphics.drawable.InsetDrawable;
import android.graphics.drawable.RippleDrawable;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.Log;
import android.util.TypedValue;
import android.view.LayoutInflater;
import android.view.TouchDelegate;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewStub;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.TextView;

import androidx.annotation.StyleRes;
import androidx.annotation.VisibleForTesting;

import com.android.car.setupwizardlib.partner.PartnerConfig;
import com.android.car.setupwizardlib.partner.PartnerConfigHelper;

import java.util.Locale;
import java.util.Objects;

/**
 * Custom layout for the Car Setup Wizard. Provides accessors for modifying elements such as buttons
 * and progress bars. Any modifications to elements built by the CarSetupWizardBaseLayout should be
 * done through methods provided by this class unless that is not possible so as to keep the state
 * internally consistent.
 */
class CarSetupWizardBaseLayout extends LinearLayout {
    private static final String TAG = CarSetupWizardBaseLayout.class.getSimpleName();
    private static final int ANIMATION_DURATION_MS = 100;

    private View mBackButton;
    private View mTitleBar;
    private Float mTitleBarElevation;
    private TextView mToolbarTitle;
    private PartnerConfigHelper mPartnerConfigHelper;

    /* <p>The Primary Toolbar Button should always be used when there is only a single action that
     * moves the wizard to the next screen (e.g. Only need a 'Skip' button).
     *
     * When there are two actions that can move the wizard to the next screen (e.g. either 'Skip'
     * or 'Let's Go' are the two options), then the Primary is used for the positive action
     * while the Secondary is used for the negative action.</p>
     */
    private Button mPrimaryToolbarButton;

    /*
     * Flag to track the primary toolbar button flat state.
     */
    private boolean mPrimaryToolbarButtonFlat;
    private View.OnClickListener mPrimaryToolbarButtonOnClick;
    private Button mSecondaryToolbarButton;
    private ProgressBar mProgressBar;

    CarSetupWizardBaseLayout(Context context) {
        this(context, null);
    }

    CarSetupWizardBaseLayout(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    CarSetupWizardBaseLayout(Context context, @Nullable AttributeSet attrs,
            int defStyleAttr) {
        this(context, attrs, defStyleAttr, 0);
    }

    /**
     * On initialization, the layout gets all of the custom attributes and initializes
     * the custom views that can be set by the user (e.g. back button, continue button).
     */
    CarSetupWizardBaseLayout(Context context, @Nullable AttributeSet attrs,
            int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);

        mPartnerConfigHelper = PartnerConfigHelper.get(context);
        TypedArray attrArray = context.getTheme().obtainStyledAttributes(
                attrs,
                R.styleable.CarSetupWizardBaseLayout,
                0, 0);

        init(attrArray);
    }

    /**
     * Inflates the layout and sets the custom views (e.g. back button, continue button).
     */
    private void init(TypedArray attrArray) {
        boolean showBackButton;

        boolean showToolbarTitle;
        String toolbarTitleText;

        boolean showPrimaryToolbarButton;
        String primaryToolbarButtonText;
        boolean primaryToolbarButtonEnabled;

        boolean showSecondaryToolbarButton;
        String secondaryToolbarButtonText;
        boolean secondaryToolbarButtonEnabled;

        boolean showProgressBar;
        boolean indeterminateProgressBar;

        try {
            showBackButton = attrArray.getBoolean(
                    R.styleable.CarSetupWizardBaseLayout_showBackButton, true);
            showToolbarTitle = attrArray.getBoolean(
                    R.styleable.CarSetupWizardBaseLayout_showToolbarTitle, false);
            toolbarTitleText = attrArray.getString(
                    R.styleable.CarSetupWizardBaseLayout_toolbarTitleText);
            showPrimaryToolbarButton = attrArray.getBoolean(
                    R.styleable.CarSetupWizardBaseLayout_showPrimaryToolbarButton, true);
            primaryToolbarButtonText = attrArray.getString(
                    R.styleable.CarSetupWizardBaseLayout_primaryToolbarButtonText);
            primaryToolbarButtonEnabled = attrArray.getBoolean(
                    R.styleable.CarSetupWizardBaseLayout_primaryToolbarButtonEnabled, true);
            mPrimaryToolbarButtonFlat = attrArray.getBoolean(
                    R.styleable.CarSetupWizardBaseLayout_primaryToolbarButtonFlat, false);
            showSecondaryToolbarButton = attrArray.getBoolean(
                    R.styleable.CarSetupWizardBaseLayout_showSecondaryToolbarButton, false);
            secondaryToolbarButtonText = attrArray.getString(
                    R.styleable.CarSetupWizardBaseLayout_secondaryToolbarButtonText);
            secondaryToolbarButtonEnabled = attrArray.getBoolean(
                    R.styleable.CarSetupWizardBaseLayout_secondaryToolbarButtonEnabled, true);
            showProgressBar = attrArray.getBoolean(
                    R.styleable.CarSetupWizardBaseLayout_showProgressBar, false);
            indeterminateProgressBar = attrArray.getBoolean(
                    R.styleable.CarSetupWizardBaseLayout_indeterminateProgressBar, true);
        } finally {
            attrArray.recycle();
        }

        LayoutInflater inflater = LayoutInflater.from(getContext());
        inflater.inflate(R.layout.car_setup_wizard_layout, this);

        // Set the back button visibility based on the custom attribute.
        setBackButton(findViewById(R.id.back_button));
        Drawable drawable = mPartnerConfigHelper.getDrawable(
                getContext(), PartnerConfig.CONFIG_TOOLBAR_BUTTON_ICON_BACK);
        if (drawable != null) {
            ((ImageView) mBackButton).setImageDrawable(drawable);
        }
        setBackButtonVisible(showBackButton);

        // Se the title bar.
        setTitleBar(findViewById(R.id.application_bar));
        mTitleBarElevation =
                getContext().getResources().getDimension(R.dimen.title_bar_drop_shadow_elevation);
        int toolbarBgColor =
                mPartnerConfigHelper.getColor(getContext(), PartnerConfig.CONFIG_TOOLBAR_BG_COLOR);
        if (toolbarBgColor != 0) {
            mTitleBar.setBackgroundColor(toolbarBgColor);
        }

        // Set the toolbar title visibility and text based on the custom attributes.
        setToolbarTitle(findViewById(R.id.toolbar_title));
        if (showToolbarTitle) {
            setToolbarTitleText(toolbarTitleText);
        } else {
            setToolbarTitleVisible(false);
        }

        // Set the primary continue button visibility and text based on the custom attributes.
        ViewStub primaryToolbarButtonStub =
                (ViewStub) findViewById(R.id.primary_toolbar_button_stub);
        // Set the button layout to flat if that attribute was set.
        if (mPrimaryToolbarButtonFlat) {
            primaryToolbarButtonStub.setLayoutResource(R.layout.flat_button);
        }
        primaryToolbarButtonStub.inflate();
        setPrimaryToolbarButton(findViewById(R.id.primary_toolbar_button));
        if (showPrimaryToolbarButton) {
            setPrimaryToolbarButtonText(primaryToolbarButtonText);
            setPrimaryToolbarButtonEnabled(primaryToolbarButtonEnabled);

            setBackground(
                    mPrimaryToolbarButton,
                    PartnerConfig.CONFIG_TOOLBAR_PRIMARY_BUTTON_BG,
                    PartnerConfig.CONFIG_TOOLBAR_PRIMARY_BUTTON_BG_COLOR);

            setButtonPadding(mPrimaryToolbarButton);
            setButtonTypeFace(mPrimaryToolbarButton);
            setButtonTextSize(mPrimaryToolbarButton);
            setButtonTextColor(
                    mPrimaryToolbarButton,
                    PartnerConfig.CONFIG_TOOLBAR_PRIMARY_BUTTON_TEXT_COLOR);
        } else {
            setPrimaryToolbarButtonVisible(false);
        }

        // Set the secondary continue button visibility and text based on the custom attributes.
        ViewStub secondaryToolbarButtonStub =
                (ViewStub) findViewById(R.id.secondary_toolbar_button_stub);
        if (showSecondaryToolbarButton || !TextUtils.isEmpty(secondaryToolbarButtonText)) {
            secondaryToolbarButtonStub.inflate();
            mSecondaryToolbarButton = findViewById(R.id.secondary_toolbar_button);
            setSecondaryToolbarButtonText(secondaryToolbarButtonText);
            setSecondaryToolbarButtonEnabled(secondaryToolbarButtonEnabled);
            setSecondaryToolbarButtonVisible(showSecondaryToolbarButton);
        }

        mProgressBar = findViewById(R.id.progress_bar);
        setProgressBarVisible(showProgressBar);
        setProgressBarIndeterminate(indeterminateProgressBar);
        int tintColor = mPartnerConfigHelper.getColor(
                getContext(),
                PartnerConfig.CONFIG_TOOLBAR_LOADING_INDICATOR_COLOR);
        if (tintColor != 0) {
            mProgressBar.setIndeterminateTintList(ColorStateList.valueOf(tintColor));
        }

        // Set orientation programmatically since the inflated layout uses <merge>
        setOrientation(LinearLayout.VERTICAL);
    }

    /**
     * Set a given view's visibility.
     */
    @VisibleForTesting
    void setViewVisible(View view, boolean visible) {
        view.setVisibility(visible ? View.VISIBLE : View.GONE);
    }

    // Add or remove the back button touch delegate depending on whether it is visible.
    @VisibleForTesting
    void updateBackButtonTouchDelegate(boolean visible) {
        if (visible) {
            // Post this action in the parent's message queue to make sure the parent
            // lays out its children before getHitRect() is called
            this.post(() -> {
                Rect delegateArea = new Rect();

                mBackButton.getHitRect(delegateArea);

                /*
                 * Update the delegate area based on the difference between the current size and
                 * the touch target size
                 */
                float touchTargetSize = getResources().getDimension(
                        R.dimen.car_touch_target_size);
                float primaryIconSize = getResources().getDimension(
                        R.dimen.car_primary_icon_size);

                int sizeDifference = (int) ((touchTargetSize - primaryIconSize) / 2);

                delegateArea.right += sizeDifference;
                delegateArea.bottom += sizeDifference;
                delegateArea.left -= sizeDifference;
                delegateArea.top -= sizeDifference;

                // Set the TouchDelegate on the parent view
                TouchDelegate touchDelegate = new TouchDelegate(delegateArea,
                        mBackButton);

                if (View.class.isInstance(mBackButton.getParent())) {
                    ((View) mBackButton.getParent()).setTouchDelegate(touchDelegate);
                }
            });
        } else {
            // Set the TouchDelegate to null if the back button is not visible.
            if (View.class.isInstance(mBackButton.getParent())) {
                ((View) mBackButton.getParent()).setTouchDelegate(null);
            }
        }
    }

    /**
     * Gets the back button.
     */
    public View getBackButton() {
        return mBackButton;
    }

    @VisibleForTesting
    final void setBackButton(View backButton) {
        mBackButton = backButton;
    }

    /**
     * Set the back button onClickListener to given listener. Can be null if the listener should
     * be overridden so no callback is made.
     */
    public void setBackButtonListener(@Nullable View.OnClickListener listener) {
        mBackButton.setOnClickListener(listener);
    }

    /**
     * Set the back button visibility to the given visibility.
     */
    public void setBackButtonVisible(boolean visible) {
        setViewVisible(mBackButton, visible);
        updateBackButtonTouchDelegate(visible);
    }

    /**
     * Gets the toolbar title.
     */
    public TextView getToolbarTitle() {
        return mToolbarTitle;
    }

    @VisibleForTesting
    final void setToolbarTitle(TextView toolbarTitle) {
        mToolbarTitle = toolbarTitle;
    }

    /**
     * Sets the header title visibility to given value.
     */
    public void setToolbarTitleVisible(boolean visible) {
        setViewVisible(mToolbarTitle, visible);
    }

    /**
     * Sets the header title text to the provided text.
     */
    public void setToolbarTitleText(String text) {
        mToolbarTitle.setText(text);
    }

    /**
     * Sets the style for the toolbar title.
     */
    public void setToolbarTitleStyle(@StyleRes int style) {
        mToolbarTitle.setTextAppearance(style);
    }

    /**
     * Gets the primary toolbar button.
     */
    public Button getPrimaryToolbarButton() {
        return mPrimaryToolbarButton;
    }

    @VisibleForTesting
    final void setPrimaryToolbarButton(Button primaryToolbarButton) {
        mPrimaryToolbarButton = primaryToolbarButton;
    }

    /**
     * Set the primary continue button visibility to the given visibility.
     */
    public void setPrimaryToolbarButtonVisible(boolean visible) {
        setViewVisible(mPrimaryToolbarButton, visible);
    }

    /**
     * Set whether the primary continue button is enabled.
     */
    public void setPrimaryToolbarButtonEnabled(boolean enabled) {
        mPrimaryToolbarButton.setEnabled(enabled);
    }

    /**
     * Set the primary continue button text to the given text.
     */
    public void setPrimaryToolbarButtonText(String text) {
        mPrimaryToolbarButton.setText(text);
    }

    /**
     * Set the primary continue button onClickListener to the given listener. Can be null if the
     * listener should be overridden so no callback is made. All changes to primary toolbar
     * button's onClickListener should be made here so they can be stored through changes to the
     * button.
     */
    public void setPrimaryToolbarButtonListener(@Nullable View.OnClickListener listener) {
        mPrimaryToolbarButtonOnClick = listener;
        mPrimaryToolbarButton.setOnClickListener(listener);
    }

    /**
     * Getter for the flatness of the primary toolbar button.
     */
    public boolean getPrimaryToolbarButtonFlat() {
        return mPrimaryToolbarButtonFlat;
    }

    /**
     * Changes the button in the primary slot to a flat theme, maintaining the text, visibility,
     * whether it is enabled, and id.
     * <p>NOTE: that other attributes set manually on the primaryToolbarButton will be lost on calls
     * to this method as the button will be replaced.</p>
     */
    public void setPrimaryToolbarButtonFlat(boolean isFlat) {
        // Do nothing if the state isn't changing.
        if (isFlat == mPrimaryToolbarButtonFlat) {
            return;
        }
        Button newPrimaryButton = createPrimaryToolbarButton(isFlat);

        ViewGroup parent = (ViewGroup) findViewById(R.id.button_container);
        int buttonIndex = parent.indexOfChild(mPrimaryToolbarButton);
        parent.removeViewAt(buttonIndex);
        parent.addView(newPrimaryButton, buttonIndex);

        // Update state of layout
        setPrimaryToolbarButton(newPrimaryButton);
        mPrimaryToolbarButtonFlat = isFlat;
    }

    @VisibleForTesting
    Button createPrimaryToolbarButton(boolean isFlat) {
        int layoutId = isFlat ? R.layout.flat_button : R.layout.primary_button;
        Button newPrimaryButton = (Button) inflate(getContext(), layoutId, null);
        newPrimaryButton.setId(mPrimaryToolbarButton.getId());
        newPrimaryButton.setVisibility(mPrimaryToolbarButton.getVisibility());
        newPrimaryButton.setEnabled(mPrimaryToolbarButton.isEnabled());
        newPrimaryButton.setText(mPrimaryToolbarButton.getText());
        newPrimaryButton.setOnClickListener(mPrimaryToolbarButtonOnClick);
        newPrimaryButton.setLayoutParams(mPrimaryToolbarButton.getLayoutParams());

        return newPrimaryButton;
    }

    /**
     * Gets the secondary toolbar button.
     */
    public Button getSecondaryToolbarButton() {
        return mSecondaryToolbarButton;
    }

    /**
     * Set the secondary continue button visibility to the given visibility.
     */
    public void setSecondaryToolbarButtonVisible(boolean visible) {
        // If not setting it visible and it hasn't been inflated yet then don't inflate.
        if (!visible && mSecondaryToolbarButton == null) {
            return;
        }
        maybeInflateSecondaryToolbarButton();
        setViewVisible(mSecondaryToolbarButton, visible);
    }

    /**
     * Sets whether the secondary continue button is enabled.
     */
    public void setSecondaryToolbarButtonEnabled(boolean enabled) {
        maybeInflateSecondaryToolbarButton();
        mSecondaryToolbarButton.setEnabled(enabled);
    }

    /**
     * Sets the secondary continue button text to the given text.
     */
    public void setSecondaryToolbarButtonText(String text) {
        maybeInflateSecondaryToolbarButton();
        mSecondaryToolbarButton.setText(text);
    }

    /**
     * Sets the secondary continue button onClickListener to the given listener. Can be null if the
     * listener should be overridden so no callback is made.
     */
    public void setSecondaryToolbarButtonListener(@Nullable View.OnClickListener listener) {
        maybeInflateSecondaryToolbarButton();
        mSecondaryToolbarButton.setOnClickListener(listener);
    }

    /**
     * Gets the progress bar.
     */
    public ProgressBar getProgressBar() {
        return mProgressBar;
    }

    /**
     * Sets the progress bar visibility to the given visibility.
     */
    public void setProgressBarVisible(boolean visible) {
        setViewVisible(mProgressBar, visible);
    }

    /**
     * Sets the progress bar indeterminate/determinate state.
     */
    public void setProgressBarIndeterminate(boolean indeterminate) {
        mProgressBar.setIndeterminate(indeterminate);
    }

    /**
     * Sets the progress bar's progress.
     */
    public void setProgressBarProgress(int progress) {
        setProgressBarIndeterminate(false);
        mProgressBar.setProgress(progress);
    }

    /**
     * Sets the locale to be used for rendering.
     */
    public void applyLocale(Locale locale) {
        if (locale == null) {
            return;
        }
        int direction = TextUtils.getLayoutDirectionFromLocale(locale);
        setLayoutDirection(direction);

        mToolbarTitle.setTextLocale(locale);
        mToolbarTitle.setLayoutDirection(direction);

        mPrimaryToolbarButton.setTextLocale(locale);
        mPrimaryToolbarButton.setLayoutDirection(direction);

        mSecondaryToolbarButton.setTextLocale(locale);
        mSecondaryToolbarButton.setLayoutDirection(direction);
    }

    /**
     * Adds elevation to the title bar in order to produce a drop shadow. An animation can be used
     * in cases where a direct elevation changes would be too jarring.
     *
     * @param animate True when a smooth animation is wanted for the adding of the elevation.
     */
    public void addElevationToTitleBar(boolean animate) {
        if (animate) {
            ValueAnimator elevationAnimator =
                    ValueAnimator.ofFloat(mTitleBar.getElevation(), mTitleBarElevation);
            elevationAnimator
                    .setDuration(ANIMATION_DURATION_MS)
                    .addUpdateListener(
                            animation -> mTitleBar.setElevation(
                                    (float) animation.getAnimatedValue()));
            elevationAnimator.start();
        } else {
            mTitleBar.setElevation(mTitleBarElevation);
        }
    }

    /**
     * Removes the elevation from the title bar, an animation can be used in cases where a direct
     * elevation changes would be too jarring.
     *
     * @param animate True when a smooth animation is wanted for the removal of the elevation.
     */
    public void removeElevationFromTitleBar(boolean animate) {
        if (animate) {
            ValueAnimator elevationAnimator =
                    ValueAnimator.ofFloat(mTitleBar.getElevation(), 0f);
            elevationAnimator
                    .setDuration(ANIMATION_DURATION_MS)
                    .addUpdateListener(
                            animation -> mTitleBar.setElevation(
                                    (float) animation.getAnimatedValue()));
            elevationAnimator.start();
        } else {
            mTitleBar.setElevation(0f);
        }
    }

    /**
     * Sets the title bar view.
     */
    private void setTitleBar(View titleBar) {
        mTitleBar = titleBar;
    }

    /**
     * A method that inflates the SecondaryToolbarButton if it is has not already been
     * inflated. If it has been inflated already this method will do nothing.
     */
    private void maybeInflateSecondaryToolbarButton() {
        ViewStub secondaryToolbarButtonStub = findViewById(R.id.secondary_toolbar_button_stub);
        // If the secondaryToolbarButtonStub is null then the stub has been inflated so there is
        // nothing to do.
        if (secondaryToolbarButtonStub != null) {
            secondaryToolbarButtonStub.inflate();
            mSecondaryToolbarButton = findViewById(R.id.secondary_toolbar_button);
            setSecondaryToolbarButtonVisible(false);

            setBackground(
                    mSecondaryToolbarButton,
                    PartnerConfig.CONFIG_TOOLBAR_SECONDARY_BUTTON_BG,
                    PartnerConfig.CONFIG_TOOLBAR_SECONDARY_BUTTON_BG_COLOR);

            setButtonPadding(mSecondaryToolbarButton);
            setButtonTypeFace(mSecondaryToolbarButton);
            setButtonTextSize(mSecondaryToolbarButton);
            setButtonTextColor(
                    mSecondaryToolbarButton,
                    PartnerConfig.CONFIG_TOOLBAR_SECONDARY_BUTTON_TEXT_COLOR);

            // Set button spacing
            float marginEnd = PartnerConfigHelper.get(getContext()).getDimension(
                    getContext(),
                    PartnerConfig.CONFIG_TOOLBAR_BUTTON_SPACING);

            MarginLayoutParams layoutParams =
                    (MarginLayoutParams) mSecondaryToolbarButton.getLayoutParams();
            layoutParams.setMarginEnd(Math.round(marginEnd));
        }
    }

    /** Sets button text color using partner overlay if exists */
    @VisibleForTesting
    void setButtonTextColor(TextView button, PartnerConfig config) {
        int color = mPartnerConfigHelper.getColor(getContext(), config);
        if (color != 0) {
            button.setTextColor(color);
        }
    }

    /**
     * Sets background using partner overlay if exists. Background color and radius are only
     * applied if background resource doesn't exist. Otherwise default background color and radius
     * may override what's set in the background.
     */
    @VisibleForTesting
    void setBackground(View view, PartnerConfig bgConfig, PartnerConfig bgColorConfig) {
        Drawable background = mPartnerConfigHelper.getDrawable(getContext(), bgConfig);
        if (background == null) {
            if (view instanceof Button) {
                setButtonRadius((Button) view);
            }
            setBackgroundColor(view, bgColorConfig);
        } else {
            view.setBackground(background);
        }
    }

    /** Sets button background color using partner overlay if exists */
    @VisibleForTesting
    void setBackgroundColor(View button, PartnerConfig config) {
        int color = mPartnerConfigHelper.getColor(getContext(), config);
        if (color != 0) {
            Drawable background = button.getBackground();
            if (background != null) {
                background.mutate().setColorFilter(color, PorterDuff.Mode.SRC_ATOP);
            }
        }
    }

    /** Sets button text size using partner overlay if exists */
    @VisibleForTesting
    void setButtonTextSize(TextView button) {
        float dimension = mPartnerConfigHelper.getDimension(
                getContext(),
                PartnerConfig.CONFIG_TOOLBAR_BUTTON_TEXT_SIZE);
        if (dimension != 0) {
            button.setTextSize(TypedValue.COMPLEX_UNIT_PX, dimension);
        }
    }

    /** Sets button type face with partner overlay if exists */
    private void setButtonTypeFace(TextView button) {
        String fontFamily = mPartnerConfigHelper.getString(
                getContext(),
                PartnerConfig.CONFIG_TOOLBAR_BUTTON_FONT_FAMILY);
        if (TextUtils.isEmpty(fontFamily)) {
            return;
        }

        Typeface typeface = Typeface.create(fontFamily, Typeface.NORMAL);
        if (Objects.equals(typeface, Typeface.DEFAULT)) {
            Log.w(TAG, String.format(
                    "Couldn't find font: %s. Setting default font.",
                    fontFamily));
        }
        button.setTypeface(typeface);
    }

    /** Sets button radius using partner overlay if exists */
    private void setButtonRadius(Button button) {
        float radius = mPartnerConfigHelper.getDimension(
                getContext(),
                PartnerConfig.CONFIG_TOOLBAR_BUTTON_RADIUS);

        GradientDrawable gradientDrawable = getGradientDrawable(button);
        if (gradientDrawable != null) {
            gradientDrawable.setCornerRadius(radius);
        }
    }

    private void setButtonPadding(Button button) {
        int hPadding = Math.round(
                PartnerConfigHelper.get(getContext()).getDimension(
                        getContext(),
                        PartnerConfig.CONFIG_TOOLBAR_BUTTON_PADDING_HORIZONTAL)
        );
        int vPadding = Math.round(
                PartnerConfigHelper.get(getContext()).getDimension(
                        getContext(),
                        PartnerConfig.CONFIG_TOOLBAR_BUTTON_PADDING_VERTICAL)
        );
        button.setPadding(hPadding, vPadding, hPadding, vPadding);
    }

    private GradientDrawable getGradientDrawable(Button button) {
        Drawable drawable = button.getBackground();
        if (drawable instanceof InsetDrawable) {
            return getGradientDrawableFromInsetDrawable((InsetDrawable) drawable);
        }

        if (drawable instanceof RippleDrawable) {
            drawable = ((RippleDrawable) drawable).getDrawable(0);
            if (drawable instanceof InsetDrawable) {
                return getGradientDrawableFromInsetDrawable((InsetDrawable) drawable);
            }
            return (GradientDrawable) drawable;
        }

        return null;
    }

    private GradientDrawable getGradientDrawableFromInsetDrawable(InsetDrawable insetDrawable) {
        return (GradientDrawable) insetDrawable.getDrawable();
    }
}
