/*
 * Copyright (C) 2017 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 CarSetupWizardLayout should be done through methods provided by this class unless that is
 * not possible so as to keep the state internally consistent.
 *
 * @deprecated Use {@link CarSetupWizardCompatLayout} or {@link CarSetupWizardDesignLayout}.
 */
public class CarSetupWizardLayout extends LinearLayout {
    private static final String TAG = CarSetupWizardLayout.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;

    public CarSetupWizardLayout(Context context) {
        this(context, null);
    }

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

    public CarSetupWizardLayout(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).
     */
    public CarSetupWizardLayout(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.CarSetupWizardLayout,
                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.CarSetupWizardLayout_showBackButton, true);
            showToolbarTitle = attrArray.getBoolean(
                    R.styleable.CarSetupWizardLayout_showToolbarTitle, false);
            toolbarTitleText = attrArray.getString(
                    R.styleable.CarSetupWizardLayout_toolbarTitleText);
            showPrimaryToolbarButton = attrArray.getBoolean(
                    R.styleable.CarSetupWizardLayout_showPrimaryToolbarButton, true);
            primaryToolbarButtonText = attrArray.getString(
                    R.styleable.CarSetupWizardLayout_primaryToolbarButtonText);
            primaryToolbarButtonEnabled = attrArray.getBoolean(
                    R.styleable.CarSetupWizardLayout_primaryToolbarButtonEnabled, true);
            mPrimaryToolbarButtonFlat = attrArray.getBoolean(
                    R.styleable.CarSetupWizardLayout_primaryToolbarButtonFlat, false);
            showSecondaryToolbarButton = attrArray.getBoolean(
                    R.styleable.CarSetupWizardLayout_showSecondaryToolbarButton, false);
            secondaryToolbarButtonText = attrArray.getString(
                    R.styleable.CarSetupWizardLayout_secondaryToolbarButtonText);
            secondaryToolbarButtonEnabled = attrArray.getBoolean(
                    R.styleable.CarSetupWizardLayout_secondaryToolbarButtonEnabled, true);
            showProgressBar = attrArray.getBoolean(
                    R.styleable.CarSetupWizardLayout_showProgressBar, false);
            indeterminateProgressBar = attrArray.getBoolean(
                    R.styleable.CarSetupWizardLayout_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();
    }
}
