package org.telegram.ui.Components;

import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.ColorFilter;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PixelFormat;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffColorFilter;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.HorizontalScrollView;
import android.widget.ImageView;
import android.widget.LinearLayout;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.graphics.ColorUtils;
import androidx.core.math.MathUtils;

import org.telegram.messenger.AndroidUtilities;
import org.telegram.messenger.ImageReceiver;
import org.telegram.messenger.MediaDataController;
import org.telegram.messenger.MessageObject;
import org.telegram.messenger.R;
import org.telegram.messenger.UserConfig;
import org.telegram.tgnet.TLRPC;
import org.telegram.ui.ActionBar.Theme;
import org.telegram.ui.Components.Premium.PremiumLockIconView;
import org.telegram.ui.SelectAnimatedEmojiDialog;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

public class EmojiTabsStrip extends ScrollableHorizontalScrollView {

    private int recentDrawableId = R.drawable.msg_emoji_recent;
    private static int[] emojiTabsDrawableIds = {
            R.drawable.msg_emoji_smiles,
            R.drawable.msg_emoji_cat,
            R.drawable.msg_emoji_food,
            R.drawable.msg_emoji_activities,
            R.drawable.msg_emoji_travel,
            R.drawable.msg_emoji_objects,
            R.drawable.msg_emoji_other,
            R.drawable.msg_emoji_flags
    };
    private static int[] emojiTabsAnimatedDrawableIds = {
            R.raw.msg_emoji_smiles,
            R.raw.msg_emoji_cat,
            R.raw.msg_emoji_food,
            R.raw.msg_emoji_activities,
            R.raw.msg_emoji_travel,
            R.raw.msg_emoji_objects,
            R.raw.msg_emoji_other,
            R.raw.msg_emoji_flags
    };
    private int settingsDrawableId = R.drawable.smiles_tab_settings;

    private boolean forceTabsShow = !UserConfig.getInstance(UserConfig.selectedAccount).isPremium();
    private boolean showSelected = true;
    private AnimatedFloat showSelectedAlpha;

    private Theme.ResourcesProvider resourcesProvider;
    private boolean includeAnimated;

    public EmojiTabButton toggleEmojiStickersTab;
    public EmojiTabButton recentTab;
    private EmojiTabButton settingsTab;
    private EmojiTabsView emojiTabs;
    private HashMap<View, Rect> removingViews = new HashMap<>();

    private int packsIndexStart;

    private ValueAnimator selectAnimator;
    private float selectT = 0f;
    private float selectAnimationT = 0f;
    private int selected = 0;
    private int selectedFullIndex = 0;
    private int wasIndex = 0;

    public boolean animateAppear = true;

    private Runnable onSettingsOpenRunnable;
    private boolean wasDrawn;
    private int animatedEmojiCacheType = AnimatedEmojiDrawable.CACHE_TYPE_TAB_STRIP;
    private int currentType;
    public boolean updateButtonDrawables = true;

    public EmojiTabsStrip(Context context, Theme.ResourcesProvider resourcesProvider, boolean includeStandard, boolean includeAnimated, int type, Runnable onSettingsOpen) {
        super(context);
        this.includeAnimated = includeAnimated;
        this.resourcesProvider = resourcesProvider;
        this.onSettingsOpenRunnable = onSettingsOpen;
        this.currentType = type;

        contentView = new LinearLayout(context) {

            HashMap<Integer, Integer> lastX = new HashMap<>();

            @Override
            protected void onLayout(boolean changed, int l, int t, int r, int b) {
                int cy = (b - t) / 2;
                if (includeAnimated) {
                    int x = getPaddingLeft() - (!recentIsShown ? AndroidUtilities.dp(30 + 3) : 0);
                    for (int i = 0; i < getChildCount(); ++i) {
                        View child = getChildAt(i);
                        if (child == settingsTab || removingViews.containsKey(child)) {
                            continue;
                        }
                        if (child != null) {
                            child.layout(x, cy - child.getMeasuredHeight() / 2, x + child.getMeasuredWidth(), cy + child.getMeasuredHeight() / 2);
                            Integer id = child instanceof EmojiTabButton ? ((EmojiTabButton) child).id : (child instanceof EmojiTabsView ? ((EmojiTabsView) child).id : null);
                            if (animateAppear && child instanceof EmojiTabButton && ((EmojiTabButton) child).newly) {
                                ((EmojiTabButton) child).newly = false;
                                child.setScaleX(0);
                                child.setScaleY(0);
                                child.setAlpha(0);
                                child.animate().scaleX(1f).scaleY(1f).alpha(1f).setDuration(200).setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT).start();
                            }
                            if (id != null) {
                                if (lastX.get(id) != null && lastX.get(id) != x) {
                                    child.setTranslationX(lastX.get(id) - x);
                                    child.animate().translationX(0).setDuration(250).setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT).start();
                                }
                                lastX.put(id, x);
                            }
                            x += child.getMeasuredWidth() + AndroidUtilities.dp(3);
                        }
                    }
                    if (settingsTab != null) {
                        x += (!recentIsShown ? AndroidUtilities.dp(30 + 3) : 0);
                        Integer id = settingsTab.id;
                        if (x + settingsTab.getMeasuredWidth() + getPaddingRight() <= EmojiTabsStrip.this.getMeasuredWidth()) {
                            settingsTab.layout(x = (r - l - getPaddingRight() - settingsTab.getMeasuredWidth()), cy - settingsTab.getMeasuredHeight() / 2, r - l - getPaddingRight(), cy + settingsTab.getMeasuredHeight() / 2);
                        } else {
                            settingsTab.layout(x, cy - settingsTab.getMeasuredHeight() / 2, x + settingsTab.getMeasuredWidth(), cy + settingsTab.getMeasuredHeight() / 2);
                        }
                        if (id != null) {
                            if (lastX.get(id) != null && lastX.get(id) != x) {
                                settingsTab.setTranslationX(lastX.get(id) - x);
                                settingsTab.animate().translationX(0).setDuration(350).start();
                            }
                            lastX.put(id, x);
                        }
                    }
                } else {
                    final int childCount = getChildCount() - (!recentIsShown ? 1 : 0);
                    int margin = (int) ((r - l - getPaddingLeft() - getPaddingRight() - childCount * AndroidUtilities.dp(30)) / (float) Math.max(1, childCount - 1));
                    int x = getPaddingLeft();
                    for (int i = 0; i < childCount; ++i) {
                        View child = getChildAt((!recentIsShown ? 1 : 0) + i);
                        if (child != null) {
                            child.layout(x, cy - child.getMeasuredHeight() / 2, x + child.getMeasuredWidth(), cy + child.getMeasuredHeight() / 2);
                            x += child.getMeasuredWidth() + margin;
                        }
                    }
                }
            }

            @Override
            protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
                final int AT_MOST = MeasureSpec.makeMeasureSpec(99999999, MeasureSpec.AT_MOST);
                int width = getPaddingLeft() + getPaddingRight() - (int) (recentIsShown ? 0 : recentTab.getAlpha() * AndroidUtilities.dp(30 + 3));
                for (int i = 0; i < getChildCount(); ++i) {
                    View child = getChildAt(i);
                    if (child != null) {
                        child.measure(AT_MOST, heightMeasureSpec);
                        width += child.getMeasuredWidth() + (i + 1 < getChildCount() ? AndroidUtilities.dp(3) : 0);
                    }
                }
                if (!includeAnimated) {
                    setMeasuredDimension(MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.getSize(heightMeasureSpec));
                    return;
                }
                setMeasuredDimension(Math.max(width, MeasureSpec.getSize(widthMeasureSpec)), MeasureSpec.getSize(heightMeasureSpec));
            }

            private Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
            private RectF from = new RectF();
            private RectF to = new RectF();
            private RectF rect = new RectF();
            private Path path = new Path();

            @Override
            protected void dispatchDraw(Canvas canvas) {
                for (Map.Entry<View, Rect> entry : removingViews.entrySet()) {
                    View view = entry.getKey();
                    if (view != null) {
                        Rect bounds = entry.getValue();
                        canvas.save();
                        canvas.translate(bounds.left, bounds.top);
                        canvas.scale(view.getScaleX(), view.getScaleY(), bounds.width() / 2f, bounds.height() / 2f);
                        view.draw(canvas);
                        canvas.restore();
                    }
                }

                if (showSelectedAlpha == null) {
                    showSelectedAlpha = new AnimatedFloat(this, 350, CubicBezierInterpolator.EASE_OUT_QUINT);
                }
                float alpha = showSelectedAlpha.set(showSelected ? 1 : 0);

                int selectFrom = (int) Math.floor(selectT), selectTo = (int) Math.ceil(selectT);
                getChildBounds(selectFrom, from);
                getChildBounds(selectTo, to);
                AndroidUtilities.lerp(from, to, selectT - selectFrom, rect);
                float isEmojiTabs = emojiTabs == null ? 0 : MathUtils.clamp(1f - Math.abs(selectT - 1), 0, 1);
                float isMiddle = 4f * selectAnimationT * (1f - selectAnimationT);
                float hw = rect.width() / 2 * (1f + isMiddle * .3f);
                float hh = rect.height() / 2 * (1f - isMiddle * .05f);
                rect.set(rect.centerX() - hw, rect.centerY() - hh, rect.centerX() + hw, rect.centerY() + hh);
                float r = AndroidUtilities.dp(AndroidUtilities.lerp(8f, 16f, isEmojiTabs));
                paint.setColor(selectorColor());
                if (forceTabsShow) {
                    paint.setAlpha((int) (paint.getAlpha() * alpha * (1f - isEmojiTabs * .5f)));
                }

                path.rewind();
                path.addRoundRect(rect, r, r, Path.Direction.CW);
                canvas.drawPath(path, paint);

                if (forceTabsShow) {
                    path.rewind();
                    getChildBounds(1, rect);
                    path.addRoundRect(rect, AndroidUtilities.dpf2(16), AndroidUtilities.dpf2(16), Path.Direction.CW);
                    paint.setColor(selectorColor());
                    paint.setAlpha((int) (paint.getAlpha() * .5f));
                    canvas.drawPath(path, paint);
                }

                if (emojiTabs != null) {
                    path.addCircle(emojiTabs.getLeft() + AndroidUtilities.dp(15), (emojiTabs.getTop() + emojiTabs.getBottom()) / 2f, AndroidUtilities.dp(15), Path.Direction.CW);
                }

                super.dispatchDraw(canvas);
                wasDrawn = true;
            }

            @Override
            protected boolean drawChild(Canvas canvas, View child, long drawingTime) {
                if (child == emojiTabs) {
                    canvas.save();
                    canvas.clipPath(path);
                    boolean res = super.drawChild(canvas, child, drawingTime);
                    canvas.restore();
                    return res;
                }
                return super.drawChild(canvas, child, drawingTime);
            }

            private void getChildBounds(int i, RectF out) {
                View child = getChildAt(MathUtils.clamp(i, 0, getChildCount() - 1));
                out.set(child.getLeft(), child.getTop(), child.getRight(), child.getBottom());
                out.set(
                        out.centerX() - out.width() / 2f * child.getScaleX(),
                        out.centerY() - out.height() / 2f * child.getScaleY(),
                        out.centerX() + out.width() / 2f * child.getScaleX(),
                        out.centerY() + out.height() / 2f * child.getScaleY()
                );
//                out.offset(recentIsShown ? recentTab.getTranslationX() : AndroidUtilities.dp(30 + 3) - recentTab.getTranslationX(), 0);
            }
        };
        contentView.setClipToPadding(false);
        contentView.setOrientation(LinearLayout.HORIZONTAL);
        setVerticalScrollBarEnabled(false);
        setHorizontalScrollBarEnabled(false);
        addView(contentView);

        if (type == SelectAnimatedEmojiDialog.TYPE_AVATAR_CONSTRUCTOR) {
            contentView.addView(toggleEmojiStickersTab = new EmojiTabButton(context, R.drawable.msg_emoji_stickers, false, false));
        }
        if (type == SelectAnimatedEmojiDialog.TYPE_TOPIC_ICON) {
            recentDrawableId = R.drawable.msg_emoji_smiles;
        }
        contentView.addView(recentTab = new EmojiTabButton(context, recentDrawableId, false, false));
        recentTab.id = "recent".hashCode();
        if (!includeAnimated) {
            for (int i = 0; i < emojiTabsDrawableIds.length; ++i) {
                contentView.addView(new EmojiTabButton(context, emojiTabsDrawableIds[i], false, i == 0));
            }
            updateClickListeners();
        } else {
            if (includeStandard) {
                contentView.addView(emojiTabs = new EmojiTabsView(context));
                emojiTabs.id = "tabs".hashCode();
            }
            packsIndexStart = contentView.getChildCount();
            if (onSettingsOpen != null) {
                contentView.addView(settingsTab = new EmojiTabButton(context, settingsDrawableId, false, true));
                settingsTab.id = "settings".hashCode();
                settingsTab.setAlpha(0);
            }
            updateClickListeners();
        }
    }

    public void showSelected(boolean show) {
        this.showSelected = show;
        this.contentView.invalidate();
    }

    private boolean recentFirstChange = true;
    private boolean recentIsShown = true;

    public void showRecent(boolean show) {
        if (recentIsShown == show) {
            return;
        }
        recentIsShown = show;
        if (recentFirstChange) {
            recentTab.setAlpha(show ? 1f : 0f);
        } else {
            recentTab.animate().alpha(show ? 1f : 0f).setDuration(200).setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT).start();
        }
        if (!show && selected == 0 || show && selected == 1) {
            select(0, !recentFirstChange);
        }
        contentView.requestLayout();
        recentFirstChange = false;
    }

    protected boolean doIncludeFeatured() {
        return true;
    }

    private boolean isFreeEmojiPack(TLRPC.StickerSet set, ArrayList<TLRPC.Document> documents) {
        if (set == null || documents == null) {
            return false;
        }
        for (int i = 0; i < documents.size(); ++i) {
            if (!MessageObject.isFreeEmoji(documents.get(i))) {
                return false;
            }
        }
        return true;
    }

    private TLRPC.Document getThumbDocument(TLRPC.StickerSet set, ArrayList<TLRPC.Document> documents) {
        if (set == null) {
            return null;
        }
        if (documents != null) {
            for (int i = 0; i < documents.size(); ++i) {
                TLRPC.Document d = documents.get(i);
                if (d.id == set.thumb_document_id) {
                    return d;
                }
            }
        }
        if (documents != null && documents.size() >= 1) {
            return documents.get(0);
        }
        return null;
    }

    private static class DelayedAnimatedEmojiDrawable extends Drawable {

        int account;
        int cacheType;
        TLRPC.Document document;
        long documentId;
        AnimatedEmojiDrawable drawable;

        int alpha = 0xFF;

        public DelayedAnimatedEmojiDrawable(int account, int cacheType, TLRPC.Document document) {
            this.account = account;
            this.cacheType = cacheType;
            this.document = document;
            if (this.document != null) {
                this.documentId = this.document.id;
            }
        }

        public DelayedAnimatedEmojiDrawable(int account, int cacheType, long documentId) {
            this.account = account;
            this.cacheType = cacheType;
            this.documentId = documentId;
        }

        public void load() {
            if (drawable != null) {
                return;
            }
            if (document != null) {
                drawable = AnimatedEmojiDrawable.make(account, cacheType, document);
            } else {
                drawable = AnimatedEmojiDrawable.make(account, cacheType, documentId);
            }
            if (lastColorFilter != null) {
                drawable.setColorFilter(lastColorFilter);
            }
            drawable.setAlpha(alpha);
            drawable.setCallback(new Callback() {
                @Override
                public void invalidateDrawable(@NonNull Drawable who) {
                    DelayedAnimatedEmojiDrawable.this.invalidateSelf();
                }
                @Override
                public void scheduleDrawable(@NonNull Drawable who, @NonNull Runnable what, long when) {
                    DelayedAnimatedEmojiDrawable.this.scheduleSelf(what, when);
                }
                @Override
                public void unscheduleDrawable(@NonNull Drawable who, @NonNull Runnable what) {
                    DelayedAnimatedEmojiDrawable.this.unscheduleSelf(what);
                }
            });
            if (view != null) {
                view.invalidate();
            }
            invalidateSelf();
        }

        public boolean equals(long documentId) {
            return this.documentId == documentId;
        }

        private View view;
        public void updateView(View view) {
            if (this.view == view) {
                return;
            }

            if (this.view != null && drawable != null) {
                drawable.removeView(this.view);
            }
            this.view = view;
            if (this.view != null && drawable != null) {
                drawable.addView(this.view);
            }
        }

        public void removeView() {
            if (view != null && drawable != null) {
                drawable.removeView(view);
            }
            view = null;
        }

        @Override
        public void draw(@NonNull Canvas canvas) {
            if (drawable != null) {
                drawable.setBounds(getBounds());
                drawable.draw(canvas);
            }
        }

        @Override
        public void setAlpha(int alpha) {
            this.alpha = alpha;
            if (drawable != null) {
                drawable.setAlpha(alpha);
            }
        }

        private ColorFilter lastColorFilter;

        @Override
        public void setColorFilter(@Nullable ColorFilter colorFilter) {
            lastColorFilter = colorFilter;
            if (drawable != null) {
                drawable.setColorFilter(lastColorFilter);
            }
        }

        @Override
        public int getOpacity() {
            return PixelFormat.TRANSPARENT;
        }
    }

    protected boolean isInstalled(EmojiView.EmojiPack pack) {
        return pack.installed;
    }

    protected void onTabCreate(EmojiTabButton button) {

    }

    protected boolean allowEmojisForNonPremium() {
        return false;
    }

    boolean first = true;
    private ValueAnimator appearAnimation;
    private int appearCount;

    public void updateEmojiPacks(ArrayList<EmojiView.EmojiPack> emojiPacks) {
        if (!includeAnimated) {
            return;
        }
        if (first && !MediaDataController.getInstance(UserConfig.selectedAccount).areStickersLoaded(MediaDataController.TYPE_EMOJIPACKS)) {
            return;
        }
        first = false;
        if (emojiPacks == null) {
            return;
        }
        int childCount = contentView.getChildCount() - packsIndexStart - (settingsTab != null ? 1 : 0);
        boolean first = childCount == 0 && emojiPacks.size() > 0 && appearCount != emojiPacks.size() && wasDrawn;
        boolean doAppearAnimation = false; // emojipackTabs.size() == 0 && emojiPacks.size() > 0 && appearCount != emojiPacks.size() && wasDrawn;
        if (appearAnimation != null && appearCount != emojiPacks.size()) {
            appearAnimation.cancel();
            appearAnimation = null;
        }
        appearCount = emojiPacks.size();
        final boolean includeFeatured = doIncludeFeatured();
        final boolean isPremium = UserConfig.getInstance(UserConfig.selectedAccount).isPremium() || allowEmojisForNonPremium();

        ArrayList<EmojiTabButton> attachedEmojiPacks = new ArrayList<>();

        for (int i = 0; i < Math.max(emojiPacks.size(), childCount); ++i) {
            EmojiTabButton currentPackButton = null;
            if (i < childCount) {
                currentPackButton = (EmojiTabButton) contentView.getChildAt(i + packsIndexStart);
            }
            EmojiView.EmojiPack newPack = null;
            if (i < emojiPacks.size()) {
                newPack = emojiPacks.get(i);
            }

            if (newPack == null) {
                if (currentPackButton != null) {
                    contentView.removeView(currentPackButton);
                }
            } else {
                final boolean free = isFreeEmojiPack(newPack.set, newPack.documents);
                DelayedAnimatedEmojiDrawable drawable = currentPackButton == null ? null : (DelayedAnimatedEmojiDrawable) currentPackButton.getDrawable();
                TLRPC.Document thumbDocument = getThumbDocument(newPack.set, newPack.documents);
                if (thumbDocument != null && (drawable == null || !drawable.equals(thumbDocument.id))) {
                    drawable = new DelayedAnimatedEmojiDrawable(UserConfig.selectedAccount, animatedEmojiCacheType, thumbDocument);
                }
                if (currentPackButton == null) {
                    currentPackButton = new EmojiTabButton(getContext(), drawable, free, false, false);
                    currentPackButton.setDrawable(drawable);
                    onTabCreate(currentPackButton);
                    contentView.addView(currentPackButton, packsIndexStart + i);
                } else if (currentPackButton.getDrawable() != drawable) {
                    currentPackButton.setDrawable(drawable);
                }
                if (currentType == SelectAnimatedEmojiDialog.TYPE_AVATAR_CONSTRUCTOR) {
                    currentPackButton.setLock(null);
                } else if (!isPremium && !free) {
                    currentPackButton.setLock(true);
                } else if (!this.isInstalled(newPack)) {
                    currentPackButton.setLock(false);
                } else {
                    currentPackButton.setLock(null);
                }
                if (doAppearAnimation && !first) {
                    currentPackButton.newly = false;
                }
            }
        }

//        for (int i = 0; i < emojipackTabs.size(); ++i) {
//            EmojiTabButton emojipackTab = emojipackTabs.get(i);
//            EmojiView.EmojiPack pack = null;
//            if (emojipackTab != null && emojipackTab.id != null) {
//                for (int j = 0; j < emojiPacks.size(); ++j) {
//                    EmojiView.EmojiPack p = emojiPacks.get(j);
//                    if (!includeFeatured && p.featured) {
//                        continue;
//                    }
//                    final int id = Objects.hash(p.set.id, p.featured);
//                    if (id == emojipackTab.id) {
//                        pack = p;
//                        break;
//                    }
//                }
//            }
//
//            if (pack == null && emojipackTab != null) {
//                Rect bounds = new Rect();
//                bounds.set(emojipackTab.getLeft(), emojipackTab.getTop(), emojipackTab.getRight(), emojipackTab.getBottom());
//                removingViews.put(emojipackTab, bounds);
//                ValueAnimator anm = ValueAnimator.ofFloat(emojipackTab.getAlpha(), 0f);
//                anm.addUpdateListener(a -> {
//                    float alpha = (float) a.getAnimatedValue();
//                    emojipackTab.setAlpha(alpha);
//                    emojipackTab.setScaleX(alpha);
//                    emojipackTab.setScaleY(alpha);
//                    contentView.invalidate();
//                });
//                anm.addListener(new AnimatorListenerAdapter() {
//                    @Override
//                    public void onAnimationEnd(Animator animation) {
//                        removingViews.remove(emojipackTab);
//                        contentView.invalidate();
//                    }
//                });
//                anm.setDuration(200);
//                anm.setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT);
//                anm.start();
//                emojipackTabs.remove(i--);
//            }
//            if (emojipackTab != null) {
//                emojipackTab.keepAttached = true;
//                attachedEmojiPacks.add(emojipackTab);
//            }
//            contentView.removeView(emojipackTab);
//        }
//        for (int i = 0; i < emojiPacks.size(); ++i) {
//            EmojiView.EmojiPack pack = emojiPacks.get(i);
//            if (!includeFeatured && pack.featured) {
//                continue;
//            }
//            final int id = Objects.hash(pack.set.id, pack.featured);
//            EmojiTabButton emojipackTab = null;
//            for (int j = 0; j < emojipackTabs.size(); ++j) {
//                EmojiTabButton tab = emojipackTabs.get(j);
//                if (tab != null && tab.id != null && tab.id == id) {
//                    emojipackTab = tab;
//                    break;
//                }
//            }
//            final boolean free = isFreeEmojiPack(pack.set, pack.documents);
//            DelayedAnimatedEmojiDrawable drawable = emojipackTab == null ? null : (DelayedAnimatedEmojiDrawable) emojipackTab.getDrawable();
//            TLRPC.Document thumbDocument = getThumbDocument(pack.set, pack.documents);
//            if (thumbDocument != null && (drawable == null || !drawable.equals(thumbDocument.id))) {
//                drawable = new DelayedAnimatedEmojiDrawable(UserConfig.selectedAccount, animatedEmojiCacheType, thumbDocument);
//            }
//            if (emojipackTab == null) {
//                emojipackTab = new EmojiTabButton(getContext(), drawable, free, false, false);
//                emojipackTab.id = id;
//                emojipackTab.setDrawable(drawable);
//                onTabCreate(emojipackTab);
//                emojipackTabs.add(emojipackTab);
//            } else if (emojipackTab.getDrawable() != drawable) {
//                emojipackTab.setDrawable(drawable);
//            }
//            if (currentType == SelectAnimatedEmojiDialog.TYPE_AVATAR_CONSTRUCTOR) {
//                emojipackTab.setLock(null);
//            } else if (!isPremium && !free) {
//                emojipackTab.setLock(true);
//            } else if (!this.isInstalled(pack)) {
//                emojipackTab.setLock(false);
//            } else {
//                emojipackTab.setLock(null);
//            }
//            if (doAppearAnimation && !first) {
//                emojipackTab.newly = false;
//            }
//            if (emojipackTab.getParent() instanceof ViewGroup) {
//                ((ViewGroup) emojipackTab.getParent()).removeView(emojipackTab);
//            }
//            contentView.addView(emojipackTab);
//        }
        if (settingsTab != null) {
            settingsTab.bringToFront();
            if (settingsTab.getAlpha() < 1) {
                settingsTab.animate().alpha(1f).setDuration(200).setInterpolator(CubicBezierInterpolator.DEFAULT).start();
            }
        }
//        if (doAppearAnimation) {
//            if (emojipackTabs != null) {
//                for (int i = 0; i < emojipackTabs.size(); ++i) {
//                    emojipackTabs.get(i).setScaleX(0);
//                    emojipackTabs.get(i).setScaleY(0);
//                }
//            }
//            appearAnimation = ValueAnimator.ofFloat(0, 1);
//            final OvershootInterpolator innerInterpolator = new OvershootInterpolator(3f);
//            appearAnimation.addUpdateListener(anm -> {
//                if (emojipackTabs == null) {
//                    return;
//                }
//                final float t = (float) anm.getAnimatedValue();
//                final int count = emojipackTabs.size();
//                final float dur = 1f / count * 4.5f;
//                for (int i = 0; i < count; ++i) {
//                    final float off = i / (float) count * (1f - dur);
//                    final float T = MathUtils.clamp((t - off) / dur, 0, 1);
//                    final float scale = innerInterpolator.getInterpolation(T);
//                    emojipackTabs.get(i).setScaleX(scale);
//                    emojipackTabs.get(i).setScaleY(scale);
//                }
//            });
//            appearAnimation.addListener(new AnimatorListenerAdapter() {
//                @Override
//                public void onAnimationCancel(Animator animation) {
//                    if (emojipackTabs == null) {
//                        return;
//                    }
//                    for (int i = 0; i < emojipackTabs.size(); ++i) {
//                        emojipackTabs.get(i).setScaleX(1);
//                        emojipackTabs.get(i).setScaleY(1);
//                    }
//                }
//            });
//            appearAnimation.setStartDelay(150);
//            appearAnimation.setDuration((emojipackTabs == null ? 0 : emojipackTabs.size()) * 75L);
//            appearAnimation.setInterpolator(CubicBezierInterpolator.EASE_OUT);
//            appearAnimation.start();
//        }
        for (int i = 0; i < attachedEmojiPacks.size(); i++) {
            attachedEmojiPacks.get(i).keepAttached = false;
            attachedEmojiPacks.get(i).updateAttachState();
        }
        updateClickListeners();
    }

    public void updateClickListeners() {
        for (int i = 0, j = 0; i < contentView.getChildCount(); ++i, ++j) {
            View child = contentView.getChildAt(i);
            if (child instanceof EmojiTabsView) {
                EmojiTabsView tabsView = (EmojiTabsView) child;
                for (int a = 0; a < tabsView.contentView.getChildCount(); ++a, ++j) {
                    final int index = j;
                    tabsView.contentView.getChildAt(a).setOnClickListener(e -> {
                        onTabClick(index);
                    });
                }
                --j;
            } else if (child != null) {
                final int index = j;
                child.setOnClickListener(e -> {
                    onTabClick(index);
                });
            }
        }
        if (settingsTab != null) {
            settingsTab.setOnClickListener(e -> {
                if (onSettingsOpenRunnable != null) {
                    onSettingsOpenRunnable.run();
                }
            });
        }
    }

    protected boolean onTabClick(int index) {
        return true;
    }

    private float paddingLeftDp = 5 + 6;

    public void setPaddingLeft(float paddingLeftDp) {
        this.paddingLeftDp = paddingLeftDp;
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        contentView.setPadding(AndroidUtilities.dp(paddingLeftDp), 0, AndroidUtilities.dp(5 + 6), 0);
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }

    public void updateColors() {
        if (recentTab != null) {
            recentTab.updateColor();
        }
    }

    public void select(int index) {
        select(index, true);
    }

    public void select(int index, boolean animated) {
        animated = animated && !first;
        if (toggleEmojiStickersTab != null) {
            index++;
        }
        if (!recentIsShown || toggleEmojiStickersTab != null) {
            index = Math.max(1, index);
        }
        selectedFullIndex = index;
        final int wasSelected = selected;
        for (int i = 0, j = 0; i < contentView.getChildCount(); ++i, ++j) {
            View child = contentView.getChildAt(i);
            int from = j;
            if (child instanceof EmojiTabsView) {
                EmojiTabsView tabs = (EmojiTabsView) child;
                for (int a = 0; a < tabs.contentView.getChildCount(); ++a, ++j) {
                    View child2 = tabs.contentView.getChildAt(a);
                    if (child2 instanceof EmojiTabButton) {
                        ((EmojiTabButton) child2).updateSelect(index == j, animated);
                    }
                }
                --j;
            } else if (child instanceof EmojiTabButton) {
                ((EmojiTabButton) child).updateSelect(index == j, animated);
            }
            if (index >= from && index <= j) {
                selected = i;
            }
        }
        if (wasSelected != selected) {
            if (selectAnimator != null) {
                selectAnimator.cancel();
            }
            final float from = selectT, to = selected;
            if (animated) {
                selectAnimator = ValueAnimator.ofFloat(0, 1);
                selectAnimator.addUpdateListener(a -> {
                    selectAnimationT = (float) a.getAnimatedValue();
                    selectT = AndroidUtilities.lerp(from, to, selectAnimationT);
                    contentView.invalidate();
                });
                selectAnimator.setDuration(350);
                selectAnimator.setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT);
                selectAnimator.start();
            } else {
                selectAnimationT = 1f;
                selectT = AndroidUtilities.lerp(from, to, selectAnimationT);
                contentView.invalidate();
            }

            if (emojiTabs != null) {
                emojiTabs.show(selected == 1 || forceTabsShow, animated);
            }

            View child = contentView.getChildAt(selected);
            if (selected >= 2) {
                scrollToVisible(child.getLeft(), child.getRight());
            } else {
                scrollTo(0);
            }
        }

        if (wasIndex != index) {
            if (emojiTabs != null && selected == 1 && index >= 1 && index <= 1 + emojiTabs.contentView.getChildCount()) {
                emojiTabs.scrollToVisible(AndroidUtilities.dp(36 * (index - 1) - 6), AndroidUtilities.dp(36 * (index - 1) - 6 + 30));
            }
            wasIndex = index;
        }
    }

    protected ColorFilter getEmojiColorFilter() {
        return Theme.chat_animatedEmojiTextColorFilter;
    }

    private int selectorColor() {
        return 0x2effffff & Theme.getColor(Theme.key_chat_emojiPanelIcon, resourcesProvider);
    }

    public void setAnimatedEmojiCacheType(int cacheType) {
        this.animatedEmojiCacheType = cacheType;
    }

    public class EmojiTabButton extends ViewGroup {
        public boolean shown = true;

        public Integer id;
        public boolean newly;
        public boolean keepAttached;
        private boolean isAnimatedEmoji;

        private ImageView imageView;
        private RLottieDrawable lottieDrawable;
        private PremiumLockIconView lockView;
        private boolean round, forceSelector;
        DelayedAnimatedEmojiDrawable animatedEmoji;
        boolean attached;

        public EmojiTabButton(Context context, int drawableId, int lottieId, boolean roundSelector, boolean forceSelector) {
            super(context);
            this.round = roundSelector;
            this.forceSelector = forceSelector;
            if (round) {
                setBackground(Theme.createCircleSelectorDrawable(selectorColor(), 0, 0));
            } else if (forceSelector) {
                setBackground(Theme.createRadSelectorDrawable(selectorColor(), 8, 8));
            }

            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                lottieDrawable = new RLottieDrawable(lottieId, "" + lottieId, AndroidUtilities.dp(24), AndroidUtilities.dp(24), false, null);
                lottieDrawable.setBounds(AndroidUtilities.dp(3), AndroidUtilities.dp(3), AndroidUtilities.dp(27), AndroidUtilities.dp(27));
                lottieDrawable.setMasterParent(this);
                lottieDrawable.setAllowDecodeSingleFrame(true);
                lottieDrawable.start();
            } else {
                imageView = new ImageView(context);
                imageView.setImageDrawable(context.getResources().getDrawable(drawableId).mutate());
                addView(imageView);
            }
            setColor(Theme.getColor(Theme.key_chat_emojiPanelIcon, resourcesProvider));
        }

        public EmojiTabButton(Context context, int drawableId, boolean roundSelector, boolean forceSelector) {
            super(context);
            this.round = roundSelector;
            this.forceSelector = forceSelector;
            if (round) {
                setBackground(Theme.createCircleSelectorDrawable(selectorColor(), 0, 0));
            } else if (forceSelector) {
                setBackground(Theme.createRadSelectorDrawable(selectorColor(), 8, 8));
            }

            imageView = new ImageView(context);
            imageView.setImageDrawable(context.getResources().getDrawable(drawableId).mutate());
            setColor(Theme.getColor(Theme.key_chat_emojiPanelIcon, resourcesProvider));

            addView(imageView);
        }

        public EmojiTabButton(Context context, Drawable drawable, boolean free, boolean roundSelector, boolean forceSelector) {
            super(context);
            this.newly = true;
            this.round = roundSelector;
            this.forceSelector = forceSelector;
            if (round) {
                setBackground(Theme.createCircleSelectorDrawable(selectorColor(), 0, 0));
            } else if (forceSelector) {
                setBackground(Theme.createRadSelectorDrawable(selectorColor(), 8, 8));
            }

            imageView = new ImageView(context) {
                @Override
                public void invalidate() {
                    super.invalidate();
                    updateLockImageReceiver();
                }

                @Override
                protected void onDraw(Canvas canvas) {

                }

                @Override
                protected void dispatchDraw(Canvas canvas) {
                    Drawable drawable = getDrawable();
                    if (drawable != null) {
                        drawable.setBounds(0, 0, getMeasuredWidth(), getMeasuredHeight());
                        drawable.setAlpha(255);
                        drawable.draw(canvas);
                    }
                }

                @Override
                public void setImageDrawable(@Nullable Drawable drawable) {
                    super.setImageDrawable(drawable);
                }
            };
            imageView.setImageDrawable(drawable);
            if (drawable instanceof AnimatedEmojiDrawable) {
                isAnimatedEmoji = true;
                imageView.setColorFilter(getEmojiColorFilter());
            }
            addView(imageView);

            lockView = new PremiumLockIconView(context, PremiumLockIconView.TYPE_STICKERS_PREMIUM_LOCKED, resourcesProvider);
            lockView.setAlpha(0f);
            lockView.setScaleX(0);
            lockView.setScaleY(0);
            updateLockImageReceiver();
            addView(lockView);

            setColor(Theme.getColor(Theme.key_chat_emojiPanelIcon, resourcesProvider));
        }

        @Override
        protected void dispatchDraw(Canvas canvas) {
            super.dispatchDraw(canvas);
            if (lottieDrawable != null && wasVisible) {
                lottieDrawable.draw(canvas);
            }
        }

        @Override
        protected boolean drawChild(Canvas canvas, View child, long drawingTime) {
            if (!wasVisible) {
                return true;
            }
            return super.drawChild(canvas, child, drawingTime);
        }

        @Override
        protected void onDraw(Canvas canvas) {
            if (!wasVisible) {
                return;
            }
            super.onDraw(canvas);
        }

        @Override
        public boolean performClick() {
            playAnimation();
            return super.performClick();
        }

        private void playAnimation() {
            if (animatedEmoji != null && animatedEmoji.drawable != null) {
                ImageReceiver imageReceiver = animatedEmoji.drawable.getImageReceiver();
                if (imageReceiver != null) {
                    if (imageReceiver.getAnimation() != null) {
                        imageReceiver.getAnimation().seekTo(0, true);
                    }
                    imageReceiver.startAnimation();
                }
            }
        }

        private void stopAnimation() {
            if (animatedEmoji != null && animatedEmoji.drawable != null) {
                ImageReceiver imageReceiver = animatedEmoji.drawable.getImageReceiver();
                if (imageReceiver != null) {
                    if (imageReceiver.getLottieAnimation() != null) {
                        imageReceiver.getLottieAnimation().setCurrentFrame(0);
                        imageReceiver.getLottieAnimation().stop();
                    } else if (imageReceiver.getAnimation() != null) {
                        imageReceiver.getAnimation().stop();
                    }
                }
            }
        }

        private boolean wasVisible;

        public void updateVisibilityInbounds(boolean visible, boolean ignore) {
            if (!wasVisible && visible) {
                if (lottieDrawable != null && !lottieDrawable.isRunning() && !ignore) {
                    lottieDrawable.setProgress(0);
                    lottieDrawable.start();
                }
            }
            if (wasVisible != visible) {
                wasVisible = visible;
                if (visible) {
                    invalidate();
                    if (lockView != null) {
                        lockView.invalidate();
                    }
                    if (imageView != null && imageView.getDrawable() instanceof DelayedAnimatedEmojiDrawable) {
                        ((DelayedAnimatedEmojiDrawable) imageView.getDrawable()).load();
                    }
                    initLock();
                    if (imageView != null) {
                        imageView.invalidate();
                    }
                } else {
                    stopAnimation();
                }
                updateAttachState();
            }
        }

        private void initLock() {
            if (lockView != null && animatedEmoji != null && animatedEmoji.drawable != null) {
                ImageReceiver imageReceiver = animatedEmoji.drawable.getImageReceiver();
                if (imageReceiver != null) {
                    lockView.setImageReceiver(imageReceiver);
                }
            }
        }

        public void setLock(Boolean lock) {
            if (lockView == null) {
                return;
            }
            if (lock == null) {
                updateLock(false);
            } else {
                updateLock(true);
                if (lock) {
                    lockView.setImageResource(R.drawable.msg_mini_lockedemoji);
                } else {
                    Drawable addIcon = getResources().getDrawable(R.drawable.msg_mini_addemoji).mutate();
                    addIcon.setColorFilter(new PorterDuffColorFilter(Color.WHITE, PorterDuff.Mode.MULTIPLY));
                    lockView.setImageDrawable(addIcon);
                }
            }
        }

        private float lockT;
        private ValueAnimator lockAnimator;

        private void updateLock(boolean enable) {
            if (lockAnimator != null) {
                lockAnimator.cancel();
            }
            if (Math.abs(lockT - (enable ? 1f : 0f)) < 0.01f) {
                return;
            }
            lockView.setVisibility(View.VISIBLE);
            lockAnimator = ValueAnimator.ofFloat(lockT, enable ? 1f : 0f);
            lockAnimator.addUpdateListener(anm -> {
                lockT = (float) anm.getAnimatedValue();
                lockView.setScaleX(lockT);
                lockView.setScaleY(lockT);
                lockView.setAlpha(lockT);
            });
            lockAnimator.addListener(new AnimatorListenerAdapter() {
                @Override
                public void onAnimationEnd(Animator animation) {
                    if (!enable) {
                        lockView.setVisibility(View.GONE);
                    }
                }
            });
            lockAnimator.setInterpolator(CubicBezierInterpolator.DEFAULT);
            lockAnimator.setDuration(200);
            lockAnimator.start();
        }

        public void updateLockImageReceiver() {
            if (lockView != null && !lockView.ready() && getDrawable() instanceof AnimatedEmojiDrawable) {
                ImageReceiver imageReceiver = ((AnimatedEmojiDrawable) getDrawable()).getImageReceiver();
                if (imageReceiver != null) {
                    lockView.setImageReceiver(imageReceiver);
                    lockView.invalidate();
                }
            }
        }

        @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            setMeasuredDimension(AndroidUtilities.dp(30), AndroidUtilities.dp(30));
            if (imageView != null) {
                imageView.measure(
                        MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(24), MeasureSpec.EXACTLY),
                        MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(24), MeasureSpec.EXACTLY)
                );
            }
            if (lockView != null) {
                lockView.measure(
                        MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(12), MeasureSpec.EXACTLY),
                        MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(12), MeasureSpec.EXACTLY)
                );
            }
        }

        @Override
        protected void onLayout(boolean changed, int l, int t, int r, int b) {
            if (imageView != null) {
                int cx = (r - l) / 2, cy = (b - t) / 2;
                imageView.layout(cx - imageView.getMeasuredWidth() / 2, cy - imageView.getMeasuredHeight() / 2, cx + imageView.getMeasuredWidth() / 2, cy + imageView.getMeasuredHeight() / 2);
            }
            if (lockView != null) {
                lockView.layout(r - l - lockView.getMeasuredWidth(), b - t - lockView.getMeasuredHeight(), r - l, b - t);
            }
        }

        public Drawable getDrawable() {
            return imageView != null ? imageView.getDrawable() : null;
        }

        public void setDrawable(Drawable drawable) {
            DelayedAnimatedEmojiDrawable newEmoji = null;
            if (drawable instanceof DelayedAnimatedEmojiDrawable) {
                newEmoji = (DelayedAnimatedEmojiDrawable) drawable;
            }
            if (animatedEmoji != newEmoji) {
                if (animatedEmoji != null && attached && wasVisible) {
                    animatedEmoji.removeView();
                }
                animatedEmoji = newEmoji;
                if (animatedEmoji != null && attached && wasVisible) {
                    animatedEmoji.updateView(imageView);
                }
                if (wasVisible) {
                    animatedEmoji.load();
                }
                initLock();
            }
            if (imageView != null) {
                imageView.setImageDrawable(drawable);
            }
        }

        @Override
        protected void onAttachedToWindow() {
            super.onAttachedToWindow();
            attached = true;
            updateAttachState();
        }

        @Override
        protected void onDetachedFromWindow() {
            super.onDetachedFromWindow();
            attached = false;
            updateAttachState();
        }

        private void updateAttachState() {
            if (animatedEmoji != null) {
                if ((keepAttached || attached) && wasVisible) {
                    animatedEmoji.updateView(imageView);
                } else {
                    animatedEmoji.removeView();
                }
            }
        }

        private float selectT;
        private boolean selected;
        private ValueAnimator selectAnimator;

        public void updateSelect(boolean selected, boolean animated) {
            if (imageView != null && imageView.getDrawable() == null) {
                return;
            }
            if (this.selected == selected) {
                return;
            }
            this.selected = selected;
            if (selectAnimator != null) {
                selectAnimator.cancel();
                selectAnimator = null;
            }

            if (!selected) {
                stopAnimation();
            }

            if (animated) {
                selectAnimator = ValueAnimator.ofFloat(selectT, selected ? 1f : 0f);
                selectAnimator.addUpdateListener(a -> {
                    selectT = (float) a.getAnimatedValue();
                    setColor(ColorUtils.blendARGB(Theme.getColor(Theme.key_chat_emojiPanelIcon, resourcesProvider), Theme.getColor(Theme.key_chat_emojiPanelIconSelected, resourcesProvider), selectT));
                });
                selectAnimator.addListener(new AnimatorListenerAdapter() {
                    @Override
                    public void onAnimationEnd(Animator animation) {
                        if (updateButtonDrawables && !round) {
                            if (selected || forceSelector) {
                                if (getBackground() == null) {
                                    setBackground(Theme.createRadSelectorDrawable(selectorColor(), 8, 8));
                                }
                            } else {
                                setBackground(null);
                            }
                        }
                    }
                });
                selectAnimator.setDuration(350);
                selectAnimator.setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT);
                selectAnimator.start();
            } else {
                selectT = selected ? 1f : 0f;
                updateColor();
            }
        }

        public void updateColor() {
            Theme.setSelectorDrawableColor(getBackground(), selectorColor(), false);
            setColor(
                    ColorUtils.blendARGB(
                            Theme.getColor(Theme.key_chat_emojiPanelIcon, resourcesProvider),
                            Theme.getColor(Theme.key_chat_emojiPanelIconSelected, resourcesProvider),
                            selectT
                    )
            );
        }

        private void setColor(int color) {
            PorterDuffColorFilter colorFilter = new PorterDuffColorFilter(color, PorterDuff.Mode.MULTIPLY);
            if (imageView != null && !isAnimatedEmoji) {
                imageView.setColorFilter(colorFilter);
                imageView.invalidate();
            }
            if (lottieDrawable != null) {
                lottieDrawable.setColorFilter(colorFilter);
                invalidate();
            }
        }
    }

    private class EmojiTabsView extends ScrollableHorizontalScrollView {
        public int id;

        public EmojiTabsView(Context context) {
            super(context);
            setSmoothScrollingEnabled(true);
            setHorizontalScrollBarEnabled(false);
            setVerticalScrollBarEnabled(false);
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                setNestedScrollingEnabled(true);
            }
            contentView = new LinearLayout(context) {
                @Override
                protected void onLayout(boolean changed, int l, int t, int r, int b) {
                    int x = getPaddingLeft(), cy = (b - t) / 2;
                    for (int i = 0; i < getChildCount(); ++i) {
                        View child = getChildAt(i);
                        if (child == settingsTab) {
                            continue;
                        }
                        if (child != null) {
                            child.layout(x, cy - child.getMeasuredHeight() / 2, x + child.getMeasuredWidth(), cy + child.getMeasuredHeight() / 2);
                            x += child.getMeasuredWidth() + AndroidUtilities.dp(2);
                        }
                    }
                }

                @Override
                protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
                    super.onMeasure(
                            Math.max(MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.makeMeasureSpec(AndroidUtilities.dp((30 + 2) * contentView.getChildCount()), MeasureSpec.EXACTLY)),
                            heightMeasureSpec
                    );
                }
            };
            contentView.setOrientation(LinearLayout.HORIZONTAL);
            addView(contentView, new LayoutParams(LayoutHelper.WRAP_CONTENT, LayoutHelper.MATCH_PARENT));

            for (int i = 0; i < emojiTabsDrawableIds.length; ++i) {
                contentView.addView(new EmojiTabButton(context, emojiTabsDrawableIds[i], emojiTabsAnimatedDrawableIds[i], true, false) {
                    @Override
                    public boolean onTouchEvent(MotionEvent ev) {
                        intercept(ev);
                        return super.onTouchEvent(ev);
                    }
                });
            }
        }

        @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            super.onMeasure(
                    MeasureSpec.makeMeasureSpec(AndroidUtilities.lerp(AndroidUtilities.dp(30), maxWidth(), showT), MeasureSpec.EXACTLY),
                    MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(30), MeasureSpec.EXACTLY)
            );
        }

        public int maxWidth() {
//            return AndroidUtilities.dp((30 + 2) * (clip() ? Math.min(5.7f, contentView.getChildCount()) : contentView.getChildCount()));
            return AndroidUtilities.dp((30 + 2) * Math.min(5.7f, contentView.getChildCount()));
        }

        private void intercept(MotionEvent ev) {
            if (shown && !scrollingAnimation) {
                switch (ev.getAction()) {
                    case MotionEvent.ACTION_UP:
                        touching = false;
                        break;
                    case MotionEvent.ACTION_DOWN:
                    case MotionEvent.ACTION_MOVE:
                        touching = true;
                        if (!scrollingAnimation) {
                            resetScrollTo();
                        }
                        EmojiTabsStrip.this.requestDisallowInterceptTouchEvent(true);
                        break;
                }
            }
        }

        @Override
        public boolean onTouchEvent(MotionEvent ev) {
            intercept(ev);
            return super.onTouchEvent(ev);
        }

        private boolean shown = forceTabsShow;
        private float showT = forceTabsShow ? 1f : 0f;

        public void show(boolean show, boolean animated) {
            if (show == shown) {
                return;
            }
            shown = show;
            if (!show) {
                scrollTo(0);
            }

            if (showAnimator != null) {
                showAnimator.cancel();
            }
            if (animated) {
                showAnimator = ValueAnimator.ofFloat(showT, show ? 1f : 0f);
                showAnimator.addUpdateListener(a -> {
                    showT = (float) a.getAnimatedValue();
                    invalidate();
                    requestLayout();
                    updateButtonsVisibility();
                    EmojiTabsStrip.this.contentView.invalidate();
                });
                showAnimator.setDuration(475);
                showAnimator.setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT);
                showAnimator.start();
            } else {
                showT = show ? 1f : 0f;
                invalidate();
                requestLayout();
                updateButtonsVisibility();
                EmojiTabsStrip.this.contentView.invalidate();
            }
        }
    }
}

class ScrollableHorizontalScrollView extends HorizontalScrollView {

    boolean touching;
    public LinearLayout contentView;
    ValueAnimator showAnimator;

    public ScrollableHorizontalScrollView(Context context) {
        super(context);
    }

    protected boolean scrollingAnimation;

    public boolean isScrolling() {
        return scrollingAnimation;
    }

    public boolean scrollToVisible(int left, int right) {
        if (getChildCount() <= 0) {
            return false;
        }
        final int padding = AndroidUtilities.dp(50);
        int to;
        if (left < getScrollX() + padding) {
            to = left - padding;
        } else if (right > getScrollX() + (getMeasuredWidth() - padding)) {
            to = right - getMeasuredWidth() + padding;
        } else {
            return false;
        }

        scrollTo(MathUtils.clamp(to, 0, getChildAt(0).getMeasuredWidth() - getMeasuredWidth()));
        return true;
    }

    private int scrollingTo = -1;
    private ValueAnimator scrollAnimator;

    public void scrollTo(int x) {
        if (scrollingTo == x) {
            return;
        }
        scrollingTo = x;
        if (scrollAnimator != null) {
            scrollAnimator.cancel();
        }
        if (this.getScrollX() == x) {
            return;
        }
        scrollAnimator = ValueAnimator.ofFloat(this.getScrollX(), x);
        scrollAnimator.addUpdateListener(a -> this.setScrollX((int) (float) a.getAnimatedValue()));
        scrollAnimator.setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT);
        scrollAnimator.setDuration(250);
        scrollAnimator.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                scrollingAnimation = false;
            }

            @Override
            public void onAnimationStart(Animator animation) {
                scrollingAnimation = true;
                if (getParent() instanceof HorizontalScrollView) {
                    ((HorizontalScrollView) getParent()).requestDisallowInterceptTouchEvent(false);
                }
            }
        });
        scrollAnimator.start();
    }

    public void resetScrollTo() {
        scrollingTo = -1;
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        super.onLayout(changed, l, t, r, b);
        updateButtonsVisibility();
    }

    @Override
    protected void onScrollChanged(int l, int t, int oldl, int oldt) {
        super.onScrollChanged(l, t, oldl, oldt);
        if (Math.abs(t - oldt) < 2 || t >= getMeasuredHeight() || t == 0) {
            if (!touching) {
                requestDisallowInterceptTouchEvent(false);
            }
        }
        updateButtonsVisibility();
    }

    void updateButtonsVisibility() {
        final int count = contentView.getChildCount();
        for (int i = 0; i < count; ++i) {
            View child = contentView.getChildAt(i);
            if (child instanceof EmojiTabsStrip.EmojiTabButton) {
                ((EmojiTabsStrip.EmojiTabButton) child).updateVisibilityInbounds(child.getRight() - getScrollX() > 0 && child.getLeft() - getScrollX() < getMeasuredWidth(), scrollingAnimation && !(showAnimator != null && showAnimator.isRunning()));
            }
        }
    }
}
