<commit_before>package io.straas.android.media.demo.widget;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.GradientDrawable;
import android.os.Build;
import android.os.Bundle;
import android.support.annotation.DrawableRes;
import android.support.annotation.IntDef;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.annotation.StyleRes;
import android.support.graphics.drawable.VectorDrawableCompat;
import android.support.v4.app.FragmentActivity;
import android.support.v4.content.ContextCompat;
import android.support.v4.media.MediaBrowserCompat.ConnectionCallback;
import android.support.v4.media.MediaMetadataCompat;
import android.support.v4.media.session.MediaControllerCompat;
import android.support.v4.media.session.MediaSessionCompat.QueueItem;
import android.support.v4.media.session.PlaybackStateCompat;
import android.support.v4.util.SparseArrayCompat;
import android.support.v4.view.GestureDetectorCompat;
import android.support.v4.widget.TextViewCompat;
import android.support.v7.widget.AppCompatImageButton;
import android.support.v7.widget.AppCompatImageView;
import android.text.SpannableStringBuilder;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.Log;
import android.view.GestureDetector;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewParent;
import android.widget.FrameLayout;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.RelativeLayout;
import android.widget.TextView;

import com.bumptech.glide.Glide;
import com.bumptech.glide.request.RequestOptions;
import com.google.android.exoplayer2.Format;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import io.straas.android.media.demo.MediaControllerCompatHelper;
import io.straas.android.media.demo.MediaControllerCompatHelper.VideoQualityInfo;
import io.straas.android.media.demo.MediaControllerCompatHelper.VideoQualityInfoCallback;
import io.straas.android.media.demo.Utils;
import io.straas.android.media.demo.widget.ui.ContentSeekBar;
import io.straas.android.media.demo.widget.ui.SwitchQualityDialog;
import io.straas.android.media.demo.widget.ui.SwitchSpeedDialog;
import io.straas.android.sdk.demo.R;
import io.straas.android.sdk.media.StraasMediaCore;
import io.straas.android.sdk.media.StraasMediaCore.ErrorReason;
import io.straas.android.sdk.media.VideoCustomMetadata;

import static io.straas.android.sdk.media.LiveEventListener.BROADCAST_STATE_DVR_PLAYBACK_AVAILABLE;
import static io.straas.android.sdk.media.LiveEventListener.BROADCAST_STATE_ENDED;
import static io.straas.android.sdk.media.LiveEventListener.BROADCAST_STATE_STARTED;
import static io.straas.android.sdk.media.LiveEventListener.BROADCAST_STATE_STOPPED;
import static io.straas.android.sdk.media.LiveEventListener.BROADCAST_STATE_UNKNOWN;
import static io.straas.android.sdk.media.LiveEventListener.BROADCAST_STATE_WAITING_FOR_STREAM;
import static io.straas.android.sdk.media.StraasMediaCore.KEY_EXTRA_TEXT_TRACKS;
import static io.straas.android.sdk.media.StraasMediaCore.LIVE_EXTRA_BROADCAST_STATE_V2;

public final class StraasPlayerView extends FrameLayout implements StraasMediaCore.UiContainer {
    private static final String TAG = StraasPlayerView.class.getSimpleName();

    public static final int PLAYBACK_MODE_VOD = 0;
    public static final int PLAYBACK_MODE_LIVE_EDGE = 1;
    public static final int PLAYBACK_MODE_LIVE_DVR = 2;

    @IntDef({PLAYBACK_MODE_VOD,
            PLAYBACK_MODE_LIVE_EDGE,
            PLAYBACK_MODE_LIVE_DVR})
    @Retention(RetentionPolicy.CLASS)
    public @interface PlaybackMode {}

    private static final int AUTO_HIDE_DELAY_MILLIS = 3000;

    private final Float[] PLAYBACK_SPEED_OPTIONS = {0.5f, 1.0f, 1.5f, 2.0f};
    private float mCurrentSpeed = 1.0f;

    private boolean mEnableDefaultWidget;
    private boolean mEnableDefaultSwitchQualityIcon;
    private boolean mEnableDefaultSwitchQualityDialog;
    private boolean mEnableDefaultSwitchSpeedIcon;
    private boolean mEnableDefaultTextTrackToggle;
    private boolean mEnableDefaultChannelName;
    private boolean mEnableDefaultSummaryViewer;
    private boolean mEnableDefaultLoadingProgressBar;
    private boolean mEnableDefaultContentSeekBar;
    private boolean mEnableDefaultTextTrack;
    private boolean mEnableDefaultPlay;
    private boolean mEnableDefaultPause;
    private boolean mEnableDefaultReplay;
    private boolean mEnableDefaultPrevious;
    private boolean mEnableDefaultNext;
    private boolean mEnableDefaultErrorMessage;
    private boolean mEnableDefaultBroadcastStateMessage;

    private boolean mIsBind;
    private boolean mIsLive = false;
    private boolean mIsLiveSeekable;
    @PlaybackMode private int mPlaybackMode = PLAYBACK_MODE_VOD;
    private boolean mCanToggleControllerUi = false;

    private View mControllerContainer;
    private View mColumnPlayPause;

    private ViewGroup mColumnSummaryViewer;
    private ViewGroup mColumnChannelName;
    private ViewGroup mColumnContentSeekBar;
    private ViewGroup mColumnLoadingBar;
    private ViewGroup mColumnPlay;
    private ViewGroup mColumnPause;
    private ViewGroup mColumnReplay;
    private ViewGroup mColumnPrevious;
    private ViewGroup mColumnNext;
    private ViewGroup mColumnDvrPlaybackAvailable;
    private ViewGroup mColumnAdPlay;
    private ViewGroup mColumnErrorMessage;
    private ViewGroup mColumnBroadcastState;

    private ViewGroup mColumnTopRight;
    private ViewGroup mColumnTopRight2;
    private ViewGroup mColumnBottomLeft;
    private ViewGroup mColumnBottomRight1;
    private ViewGroup mColumnBottomRight2;

    private TextView mChannelNameTextView;
    private TextView mSummaryViewerTextView;
    private TextView mErrorMessageTextView;
    private TextView mLivePositionTimeTextView;
    private View mBroadcastStateView;
    private View mSwitchQualityView;
    private View mSwitchSpeedView;
    private View mTextTrackToggle;
    private View mLogoView;
    private ContentSeekBar mContentSeekBar;
    private TextView mTextTrackView;
    private View mDvrPlaybackAvailableView;

    private FrameLayout mVideoView;
    private FrameLayout mAdView;
    private ImageView mImagePoster;
    private ViewGroup mTextTrack;

    private FragmentActivity mFragmentActivity;

    private Bundle mMediaExtras;
    private MediaMetadataCompat mLastMediaMetadata;
    private PlaybackStateCompat mLastPlaybackStateCompat;
    private StraasMediaCore mStraasMediaCore;
    private int mImageButtonBackground;
    private Context mThemeContext;
    private GestureDetectorCompat mGestureDetector, mGestureTapDetector, mGestureFakeDetector;
    private SwitchQualityViewClickListener mSwitchQualityViewListener;
    private ChannelNameMetadataListener mChannelNameMetadataListener = new ChannelNameMetadataListener();
    private SummaryViewerMetadataListener mSummaryViewerMetadataListener = new SummaryViewerMetadataListener();
    private ErrorMessageListener mErrorMessageListener = new ErrorMessageListener();
    private LivePositionTimeListener mLivePositionTimeListener = new LivePositionTimeListener();
    private BroadcastStateListener mBroadcastStateListener = new BroadcastStateListener();

    private List<ConnectionCallback> mMediaConnectedListenerList = new ArrayList<>();
    private SparseArrayCompat<ViewGroup> mCustomColumnList = new SparseArrayCompat<>();
    private List<QueueItem> mLastQueueList;
    private int mUIBroadcastState = BROADCAST_STATE_UNKNOWN;

    public interface SwitchQualityViewClickListener {
        void onFormatCallback(ArrayList<Format> formats, int currentIndex);
    }

    public static final int CUSTOM_COLUMN_TOP_RIGHT = 0;
    public static final int CUSTOM_COLUMN_BOTTOM_LEFT = 1;
    public static final int CUSTOM_COLUMN_BOTTOM_RIGHT1 = 2;
    public static final int CUSTOM_COLUMN_BOTTOM_RIGHT2 = 3;
    public static final int CUSTOM_COLUMN_TOP_RIGHT2 = 4;

    @IntDef({CUSTOM_COLUMN_TOP_RIGHT, CUSTOM_COLUMN_BOTTOM_LEFT, CUSTOM_COLUMN_BOTTOM_RIGHT1,
            CUSTOM_COLUMN_BOTTOM_RIGHT2, CUSTOM_COLUMN_TOP_RIGHT2})
    @Retention(RetentionPolicy.SOURCE)
    public @interface CustomColumnPosition {
    }

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

    public StraasPlayerView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public StraasPlayerView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);

        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.StraasLayout, defStyleAttr, 0);
        getCustomizedAttr(typedArray);
        typedArray.recycle();
    }

    /**
     * Initialize a StrassPlayerView, which can be used to generate layout and control UI.
     *
     * @param fragmentActivity A FragmentActivity which use StraasPlayerView.
     */
    public void initialize(@NonNull FragmentActivity fragmentActivity) {
        initialize(fragmentActivity, null);
    }

    /**
     * Initialize a StrassPlayerView, which can be used to generate layout and control UI.
     *
     * @param fragmentActivity A FragmentActivity which use StraasPlayerView.
     * @param configuration    A configuration for whether default widget to use or not.
     */
    public void initialize(@NonNull FragmentActivity fragmentActivity, @Nullable StraasConfiguration configuration) {

        mFragmentActivity = fragmentActivity;

        if (configuration != null) {
            initConfiguration(configuration);
        }

        init();
    }

    public Context getThemeContext() {
        return mThemeContext;
    }

    private void init() {
        ViewGroup straasMainContainer = (ViewGroup) LayoutInflater.from(getContext())
                .inflate(R.layout.straas_main_container, this, false);
        mThemeContext = straasMainContainer.getContext();
        int[] attr = new int[]{R.attr.selectableItemBackgroundBorderless};
        TypedArray typedArray = mThemeContext.obtainStyledAttributes(attr);
        mImageButtonBackground = Build.VERSION.SDK_INT > 21 ? typedArray.getResourceId(0, 0) : 0;
        typedArray.recycle();

        mControllerContainer = straasMainContainer.findViewById(R.id.controllerContainer);

        straasMainContainer.findViewById(R.id.upContainer).setBackground(
                new GradientDrawable(GradientDrawable.Orientation.BOTTOM_TOP,
                        new int[]{ContextCompat.getColor(mThemeContext, android.R.color.transparent),
                                ContextCompat.getColor(mThemeContext, R.color.color_controller_background_dark)}));
        straasMainContainer.findViewById(R.id.bottomContainer).setBackground(
                new GradientDrawable(GradientDrawable.Orientation.TOP_BOTTOM,
                        new int[]{ContextCompat.getColor(mThemeContext, android.R.color.transparent),
                                ContextCompat.getColor(mThemeContext, R.color.color_controller_background_dark)}));

        mVideoView = straasMainContainer.findViewById(R.id.videoSurfaceView);
        mTextTrack = straasMainContainer.findViewById(R.id.textTrack);
        mImagePoster = new ImageView(getThemeContext());

        initColumn(straasMainContainer);

        mGestureTapDetector = new GestureDetectorCompat(getContext(), new GestureDetector.SimpleOnGestureListener() {
            @Override
            public boolean onSingleTapUp(MotionEvent event) {
                if (!mCanToggleControllerUi) {
                    return false;
                }

                Utils.toggleViewVisibilityWithAnimation(AUTO_HIDE_DELAY_MILLIS, mControllerContainer, mColumnPlayPause);
                return true;
            }

            @Override
            public boolean onDown(MotionEvent e) {
                return true;
            }
        });

        mGestureFakeDetector = new GestureDetectorCompat(getContext(), new GestureDetector.SimpleOnGestureListener());

        if (mEnableDefaultWidget) {
            if (mEnableDefaultSwitchQualityIcon) {
                View switchQualityView = View.inflate(mThemeContext, R.layout.switch_quality_layout, null);
                setSwitchQualityViewPosition(switchQualityView, CUSTOM_COLUMN_TOP_RIGHT);
            }
            if (mEnableDefaultSwitchSpeedIcon) {
                View switchQualityView = View.inflate(mThemeContext, R.layout.switch_speed_layout, null);
                setSwitchSpeedViewPosition(switchQualityView, CUSTOM_COLUMN_TOP_RIGHT2);
            }
            if (mEnableDefaultTextTrackToggle) {
                View textTrackToggleView = View.inflate(mThemeContext, R.layout.text_track_toggle, null);
                setTextTrackToggleViewPosition(textTrackToggleView, CUSTOM_COLUMN_BOTTOM_RIGHT2);
            }
            if (mEnableDefaultChannelName) {
                TextView channelNameTextView = (TextView) View.inflate(mThemeContext, R.layout.channel_name, null);
                setCustomChannelName(channelNameTextView);
            }
            if (mEnableDefaultSummaryViewer) {
                TextView summaryViewerTextView = (TextView) View.inflate(mThemeContext, R.layout.summary_viewer, null);
                TextViewCompat.setCompoundDrawablesRelativeWithIntrinsicBounds(summaryViewerTextView,
                        VectorDrawableCompat.create(getResources(), R.drawable.ic_eye_24dp, null), null, null, null);
                setCustomSummaryViewerView(summaryViewerTextView);
            }
            if (mEnableDefaultLoadingProgressBar) {
                ProgressBar progressBar = (ProgressBar) View.inflate(mThemeContext, R.layout.loading_progress_bar, null);
                setCustomLoadingProgressBar(progressBar);

            }
            if (mEnableDefaultContentSeekBar) {
                ContentSeekBar contentSeekBar = new ContentSeekBar(mThemeContext);
                setCustomContentSeekBar(contentSeekBar);
            }
            if (mEnableDefaultTextTrack) {
                TextView textTrackView = (TextView) View.inflate(mThemeContext, R.layout.text_track, null);
                setCustomTextTrack(textTrackView);
            }
            if (mEnableDefaultPlay) {
                setCustomPlayIcon(R.drawable.ic_play_arrow_48dp);
            }
            if (mEnableDefaultPause) {
                setCustomPauseIcon(R.drawable.ic_pause_48dp);
            }
            if (mEnableDefaultReplay) {
                setCustomReplayIcon(R.drawable.ic_replay_48dp);
            }
            if (mEnableDefaultPrevious) {
                setCustomSkipToPreviousIcon(R.drawable.ic_skip_previous_48dp);
            }
            if (mEnableDefaultNext) {
                setCustomSkipToNextIcon(R.drawable.ic_skip_next_48px);
            }
            if (mEnableDefaultErrorMessage) {
                TextView errorMessageTextView = (TextView) View.inflate(mThemeContext, R.layout.error_message, null);
                Drawable drawable = VectorDrawableCompat.create(getResources(), R.drawable.ic_error_player, null);
                TextViewCompat.setCompoundDrawablesRelativeWithIntrinsicBounds(errorMessageTextView, drawable, null, null, null);
                setCustomErrorMessage(errorMessageTextView);
            }
            if (mEnableDefaultBroadcastStateMessage) {
                View broadcastStateOffline = View.inflate(mThemeContext, R.layout.broadcast_offline, null);
                setCustomBroadcastState(broadcastStateOffline);
            }
        }

        mAdView = straasMainContainer.findViewById(R.id.adSurfaceView);
        addView(straasMainContainer);

        setAutoHideControllerUiWhenTouch(true);
    }

    public void hideControllerViews() {
        mControllerContainer.setVisibility(GONE);
        mColumnPlayPause.setVisibility(GONE);
        mColumnAdPlay.setVisibility(GONE);
        mColumnLoadingBar.setVisibility(GONE);
        mColumnBroadcastState.setVisibility(GONE);
        mColumnErrorMessage.setVisibility(GONE);
    }

    private void initConfiguration(StraasConfiguration configuration) {
        mEnableDefaultWidget = configuration.isEnableDefaultWidget();
        mEnableDefaultSwitchQualityIcon = configuration.isEnableDefaultSwitchQuality();
        mEnableDefaultSwitchSpeedIcon = configuration.isEnableDefaultSwitchSpeed();
        mEnableDefaultTextTrackToggle = configuration.isEnableDefaultTextTrackToggle();
        mEnableDefaultChannelName = configuration.isEnableDefaultChannelName();
        mEnableDefaultSummaryViewer = configuration.isEnableDefaultSummaryViewer();
        mEnableDefaultLoadingProgressBar = configuration.isEnableDefaultLoadingProgressBar();
        mEnableDefaultContentSeekBar = configuration.isEnableDefaultContentProgressBar();
        mEnableDefaultTextTrack = configuration.isEnableDefaultTextTrack();
        mEnableDefaultPlay = configuration.isEnableDefaultPlay();
        mEnableDefaultPause = configuration.isEnableDefaultPause();
        mEnableDefaultReplay = configuration.isEnableDefaultReplay();
        mEnableDefaultPrevious = configuration.isEnableDefaultSkipToPrevious();
        mEnableDefaultNext = configuration.isEnableDefaultSkipToNext();
        mEnableDefaultErrorMessage = configuration.isEnableDefaultErrorMessage();
        mEnableDefaultBroadcastStateMessage = configuration.isEnableDefaultBroadcastStateMessage();
    }

    private final MediaControllerCompat.Callback mMediaControllerCallback = new MediaControllerCompat.Callback() {
        @Override
        public void onQueueChanged(List<QueueItem> queue) {
            mLastQueueList = queue;
            if (mLastQueueList == null) {
                mLastMediaMetadata = null;
                if (mColumnPrevious.getVisibility() != GONE) {
                    mColumnPrevious.setVisibility(GONE);
                }
                if (mColumnNext.getVisibility() != GONE) {
                    mColumnNext.setVisibility(GONE);
                }
            }
        }

        @Override
        public void onSessionDestroyed() {
        }

        @Override
        public void onMetadataChanged(MediaMetadataCompat metadata) {
            if (metadata == null || (mLastMediaMetadata != null &&
                    TextUtils.equals(metadata.getString(MediaMetadataCompat.METADATA_KEY_MEDIA_ID),
                            mLastMediaMetadata.getString(MediaMetadataCompat.METADATA_KEY_MEDIA_ID)) &&
                    TextUtils.equals(metadata.getString(MediaMetadataCompat.METADATA_KEY_DISPLAY_TITLE),
                            mLastMediaMetadata.getString(MediaMetadataCompat.METADATA_KEY_DISPLAY_TITLE)) &&
                    metadata.getBundle().getBoolean(VideoCustomMetadata.CUSTOM_METADATA_IS_LIVE_LOW_LATENCY_FIRST) ==
                            mLastMediaMetadata.getBundle().getBoolean(VideoCustomMetadata.CUSTOM_METADATA_IS_LIVE_LOW_LATENCY_FIRST))) {
                return;
            }

            mLastMediaMetadata = metadata;
            String mediaId = mLastMediaMetadata.getString(MediaMetadataCompat.METADATA_KEY_MEDIA_ID);
            if (TextUtils.isEmpty(mediaId)) {
                return;
            }

            mIsLive = mediaId.startsWith(StraasMediaCore.LIVE_ID_PREFIX);

            if (mLastQueueList != null) {
                if (mLastPlaybackStateCompat.getActiveQueueItemId() == 0) {
                    if (mColumnPrevious.getVisibility() != GONE) {
                        mColumnPrevious.setVisibility(GONE);
                    }
                } else if (mColumnPrevious.getVisibility() != VISIBLE) {
                    mColumnPrevious.setVisibility(VISIBLE);
                }

                if (mLastPlaybackStateCompat.getActiveQueueItemId() == mLastQueueList.size() - 1) {
                    if (mColumnNext.getVisibility() != GONE) {
                        mColumnNext.setVisibility(GONE);
                    }
                } else if (mColumnNext.getVisibility() != VISIBLE) {
                    mColumnNext.setVisibility(VISIBLE);
                }
            }

            String title = metadata.getString(MediaMetadataCompat.METADATA_KEY_DISPLAY_TITLE);
            mChannelNameMetadataListener.onMetaChanged(mChannelNameTextView, title);

            if (!isPosterAddedIntoVideoContainer()) {
                getVideoContainer().addView(mImagePoster, getVideoContainer().getChildCount());
            }
            if (metadata.getBundle().containsKey(StraasMediaCore.KEY_VIDEO_RENDER_TYPE)
                    && metadata.getBundle().getInt(StraasMediaCore.KEY_VIDEO_RENDER_TYPE) == StraasMediaCore.VIDEO_RENDER_TYPE_NONE) {
                mImagePoster.setVisibility(VISIBLE);
                boolean hasAlbumArtUri = metadata.getString(MediaMetadataCompat.METADATA_KEY_ALBUM_ART_URI) != null;
                Glide.with(getThemeContext())
                        .setDefaultRequestOptions(new RequestOptions()
                                .placeholder(android.R.color.black))
                        .load(hasAlbumArtUri
                                ? metadata.getString(MediaMetadataCompat.METADATA_KEY_ALBUM_ART_URI)
                                : ContextCompat.getDrawable(mImagePoster.getContext(),
                                R.drawable.vod_thumbnail_audio))
                        .into(mImagePoster);
            } else {
                mImagePoster.setVisibility(GONE);
            }
        }

        @Override
        public void onCaptioningEnabledChanged(boolean enabled) {
            super.onCaptioningEnabledChanged(enabled);
            if (mTextTrackToggle != null) {
                mTextTrackToggle.setActivated(enabled);
            }
        }

        @Override
        public void onPlaybackStateChanged(PlaybackStateCompat state) {
            if (state == null || (mLastPlaybackStateCompat != null && mLastPlaybackStateCompat.getState() == state.getState() &&
                    mLastPlaybackStateCompat.getActiveQueueItemId() == state.getActiveQueueItemId())) {
                return;
            }
            if (mLastPlaybackStateCompat == null && mTextTrackView != null) {
                MediaControllerCompatHelper.setCaptionEnable(getMediaControllerCompat(), true);
            }
            mLastPlaybackStateCompat = state;
            if (!TextUtils.isEmpty(state.getErrorMessage())) {
                @ErrorReason.ErrorReasonType String errorType = state.getErrorMessage().toString();
                mErrorMessageListener.onError(mErrorMessageTextView, errorType);
                if (mIsLive) {
                    Bundle mediaExtras = (mMediaExtras != null) ? mMediaExtras : getMediaControllerCompat().getExtras();

                    handleBroadcastStateV2(mediaExtras, true);
                }
                if (getKeepScreenOn()) {
                    setKeepScreenOn(false);
                }
                return;
            }

            if (mColumnErrorMessage.getVisibility() != GONE) {
                setErrorMessageVisibility(GONE);
            }

            if (state.getState() == PlaybackStateCompat.STATE_PLAYING) {
                setErrorMessageVisibility(GONE);
                setBroadcastStateVisibility(GONE);
                if (mControllerContainer.getVisibility() != GONE) {
                    Utils.toggleViewVisibilityWithAnimation(AUTO_HIDE_DELAY_MILLIS, mControllerContainer, mColumnPlayPause);
                }
            }

            int loadingProgressBarVisibility = GONE;

            if (state.getActiveQueueItemId() == StraasMediaCore.AD_PLAYBACK_ID) {

                if (mControllerContainer.getVisibility() != GONE) {
                    mControllerContainer.setVisibility(GONE);
                }

                if (mColumnPlayPause.getVisibility() != GONE) {
                    mColumnPlayPause.setVisibility(GONE);
                }

                switch (state.getState()) {
                    case PlaybackStateCompat.STATE_BUFFERING:
                        loadingProgressBarVisibility = VISIBLE;
                        break;
                    case PlaybackStateCompat.STATE_PLAYING:
                        mColumnAdPlay.setVisibility(GONE);
                        mCanToggleControllerUi = false;
                        break;
                    case PlaybackStateCompat.STATE_PAUSED:
                        mColumnAdPlay.setVisibility(VISIBLE);
                        break;
                    case PlaybackStateCompat.STATE_STOPPED:
                        // After AD playing ends, SDK player will seek the live streaming to
                        // the real-time coverage of live automatically for all kinds of live:
                        // normal live, low latency, and live-dvr
                        if (mIsLive) {
                            refreshLiveDvrUiStatus(PLAYBACK_MODE_LIVE_EDGE);
                        }
                        break;
                }
            } else {
                if (mColumnAdPlay.getVisibility() != GONE) {
                    mColumnAdPlay.setVisibility(GONE);
                }

                switch (state.getState()) {
                    case PlaybackStateCompat.STATE_BUFFERING:
                        loadingProgressBarVisibility = VISIBLE;

                        mColumnPlay.setVisibility(GONE);
                        mColumnPause.setVisibility(GONE);
                        break;
                    case PlaybackStateCompat.STATE_PLAYING:
                        mCanToggleControllerUi = true;

                        switchToPause();
                        if (!getKeepScreenOn()) {
                            setKeepScreenOn(true);
                        }
                        break;
                    case PlaybackStateCompat.STATE_PAUSED:
                        if (mPlaybackMode == PLAYBACK_MODE_LIVE_EDGE) {
                            refreshLiveDvrUiStatus(PLAYBACK_MODE_LIVE_DVR);
                        }

                        mCanToggleControllerUi = false;

                        showControllerUi();
                        showPlayUi();
                        if (getKeepScreenOn()) {
                            setKeepScreenOn(false);
                        }
                        break;
                    case PlaybackStateCompat.STATE_NONE:
                        mCanToggleControllerUi = false;
                        hideControllerViews();
                        refreshLiveDvrUiStatus(PLAYBACK_MODE_LIVE_EDGE);
                        if (getKeepScreenOn()) {
                            setKeepScreenOn(false);
                        }
                    case PlaybackStateCompat.STATE_STOPPED:
                        mCanToggleControllerUi = true;
                        if (mIsLive) {
                            Bundle mediaExtras = (mMediaExtras != null) ? mMediaExtras :
                                    getMediaControllerCompat().getExtras();

                            handleBroadcastStateV2(mediaExtras, true);
                        }
                        switchToReplay();
                        if (getKeepScreenOn()) {
                            setKeepScreenOn(false);
                        }
                        break;
                }
            }

            setLoadingProgressBarVisible(loadingProgressBarVisibility == VISIBLE);
        }

        @Override
        public void onSessionEvent(String event, Bundle extras) {
            switch (event) {
                case StraasMediaCore.EVENT_MEDIA_BROWSER_SERVICE_ERROR:
                    mErrorMessageListener.onError(mErrorMessageTextView,
                            extras.getString(StraasMediaCore.KEY_MEDIA_BROWSER_ERROR_REASON));
                    break;
            }
        }

        @Override
        public void onExtrasChanged(Bundle extras) {
            handleTextTrackExtra(extras);

            mMediaExtras = extras;

            if (mIsLive) {
                boolean isLiveSeekable = extras.getBoolean(VideoCustomMetadata.LIVE_DVR_ENABLED) &&
                        !extras.getBoolean(VideoCustomMetadata.CUSTOM_METADATA_IS_LIVE_LOW_LATENCY_FIRST);
                switchMode(true, isLiveSeekable);
                if (isLiveSeekable) {
                    setCustomDvrPlaybackAvailable(View.inflate(mThemeContext, R.layout.dvr_playback_available, null));
                }

                boolean isStopPlay = mLastPlaybackStateCompat != null &&
                        (mLastPlaybackStateCompat.getState() == PlaybackStateCompat.STATE_STOPPED ||
                                mLastPlaybackStateCompat.getState() == PlaybackStateCompat.STATE_NONE ||
                                mLastPlaybackStateCompat.getState() == PlaybackStateCompat.STATE_ERROR);
                handleBroadcastStateV2(extras, isStopPlay);
            } else {
                MediaControllerCompat controller = MediaControllerCompat.getMediaController(mFragmentActivity);
                if (controller != null) {
                    MediaControllerCompatHelper.setPlaybackSpeed(controller, mCurrentSpeed);
                }
                switchMode(false, false);
            }

            long summaryViewer = extras.getLong(VideoCustomMetadata.PLAY_COUNT_SUM);
            mSummaryViewerMetadataListener.onMetaChanged(mSummaryViewerTextView, summaryViewer);
        }

        private boolean isPosterAddedIntoVideoContainer() {<commit_msg>feat: Move poster setting to onExtrasChanged(...).<commit_after>package io.straas.android.media.demo.widget;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.GradientDrawable;
import android.os.Build;
import android.os.Bundle;
import android.support.annotation.DrawableRes;
import android.support.annotation.IntDef;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.annotation.StyleRes;
import android.support.graphics.drawable.VectorDrawableCompat;
import android.support.v4.app.FragmentActivity;
import android.support.v4.content.ContextCompat;
import android.support.v4.media.MediaBrowserCompat.ConnectionCallback;
import android.support.v4.media.MediaMetadataCompat;
import android.support.v4.media.session.MediaControllerCompat;
import android.support.v4.media.session.MediaSessionCompat.QueueItem;
import android.support.v4.media.session.PlaybackStateCompat;
import android.support.v4.util.SparseArrayCompat;
import android.support.v4.view.GestureDetectorCompat;
import android.support.v4.widget.TextViewCompat;
import android.support.v7.widget.AppCompatImageButton;
import android.support.v7.widget.AppCompatImageView;
import android.text.SpannableStringBuilder;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.Log;
import android.view.GestureDetector;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewParent;
import android.widget.FrameLayout;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.RelativeLayout;
import android.widget.TextView;

import com.bumptech.glide.Glide;
import com.bumptech.glide.request.RequestOptions;
import com.google.android.exoplayer2.Format;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import io.straas.android.media.demo.MediaControllerCompatHelper;
import io.straas.android.media.demo.MediaControllerCompatHelper.VideoQualityInfo;
import io.straas.android.media.demo.MediaControllerCompatHelper.VideoQualityInfoCallback;
import io.straas.android.media.demo.Utils;
import io.straas.android.media.demo.widget.ui.ContentSeekBar;
import io.straas.android.media.demo.widget.ui.SwitchQualityDialog;
import io.straas.android.media.demo.widget.ui.SwitchSpeedDialog;
import io.straas.android.sdk.demo.R;
import io.straas.android.sdk.media.StraasMediaCore;
import io.straas.android.sdk.media.StraasMediaCore.ErrorReason;
import io.straas.android.sdk.media.VideoCustomMetadata;

import static io.straas.android.sdk.media.LiveEventListener.BROADCAST_STATE_DVR_PLAYBACK_AVAILABLE;
import static io.straas.android.sdk.media.LiveEventListener.BROADCAST_STATE_ENDED;
import static io.straas.android.sdk.media.LiveEventListener.BROADCAST_STATE_STARTED;
import static io.straas.android.sdk.media.LiveEventListener.BROADCAST_STATE_STOPPED;
import static io.straas.android.sdk.media.LiveEventListener.BROADCAST_STATE_UNKNOWN;
import static io.straas.android.sdk.media.LiveEventListener.BROADCAST_STATE_WAITING_FOR_STREAM;
import static io.straas.android.sdk.media.StraasMediaCore.KEY_EXTRA_TEXT_TRACKS;
import static io.straas.android.sdk.media.StraasMediaCore.LIVE_EXTRA_BROADCAST_STATE_V2;

public final class StraasPlayerView extends FrameLayout implements StraasMediaCore.UiContainer {
    private static final String TAG = StraasPlayerView.class.getSimpleName();

    public static final int PLAYBACK_MODE_VOD = 0;
    public static final int PLAYBACK_MODE_LIVE_EDGE = 1;
    public static final int PLAYBACK_MODE_LIVE_DVR = 2;

    @IntDef({PLAYBACK_MODE_VOD,
            PLAYBACK_MODE_LIVE_EDGE,
            PLAYBACK_MODE_LIVE_DVR})
    @Retention(RetentionPolicy.CLASS)
    public @interface PlaybackMode {}

    private static final int AUTO_HIDE_DELAY_MILLIS = 3000;

    private final Float[] PLAYBACK_SPEED_OPTIONS = {0.5f, 1.0f, 1.5f, 2.0f};
    private float mCurrentSpeed = 1.0f;

    private boolean mEnableDefaultWidget;
    private boolean mEnableDefaultSwitchQualityIcon;
    private boolean mEnableDefaultSwitchQualityDialog;
    private boolean mEnableDefaultSwitchSpeedIcon;
    private boolean mEnableDefaultTextTrackToggle;
    private boolean mEnableDefaultChannelName;
    private boolean mEnableDefaultSummaryViewer;
    private boolean mEnableDefaultLoadingProgressBar;
    private boolean mEnableDefaultContentSeekBar;
    private boolean mEnableDefaultTextTrack;
    private boolean mEnableDefaultPlay;
    private boolean mEnableDefaultPause;
    private boolean mEnableDefaultReplay;
    private boolean mEnableDefaultPrevious;
    private boolean mEnableDefaultNext;
    private boolean mEnableDefaultErrorMessage;
    private boolean mEnableDefaultBroadcastStateMessage;

    private boolean mIsBind;
    private boolean mIsLive = false;
    private boolean mIsLiveSeekable;
    @PlaybackMode private int mPlaybackMode = PLAYBACK_MODE_VOD;
    private boolean mCanToggleControllerUi = false;

    private View mControllerContainer;
    private View mColumnPlayPause;

    private ViewGroup mColumnSummaryViewer;
    private ViewGroup mColumnChannelName;
    private ViewGroup mColumnContentSeekBar;
    private ViewGroup mColumnLoadingBar;
    private ViewGroup mColumnPlay;
    private ViewGroup mColumnPause;
    private ViewGroup mColumnReplay;
    private ViewGroup mColumnPrevious;
    private ViewGroup mColumnNext;
    private ViewGroup mColumnDvrPlaybackAvailable;
    private ViewGroup mColumnAdPlay;
    private ViewGroup mColumnErrorMessage;
    private ViewGroup mColumnBroadcastState;

    private ViewGroup mColumnTopRight;
    private ViewGroup mColumnTopRight2;
    private ViewGroup mColumnBottomLeft;
    private ViewGroup mColumnBottomRight1;
    private ViewGroup mColumnBottomRight2;

    private TextView mChannelNameTextView;
    private TextView mSummaryViewerTextView;
    private TextView mErrorMessageTextView;
    private TextView mLivePositionTimeTextView;
    private View mBroadcastStateView;
    private View mSwitchQualityView;
    private View mSwitchSpeedView;
    private View mTextTrackToggle;
    private View mLogoView;
    private ContentSeekBar mContentSeekBar;
    private TextView mTextTrackView;
    private View mDvrPlaybackAvailableView;

    private FrameLayout mVideoView;
    private FrameLayout mAdView;
    private ImageView mImagePoster;
    private ViewGroup mTextTrack;

    private FragmentActivity mFragmentActivity;

    private Bundle mMediaExtras;
    private MediaMetadataCompat mLastMediaMetadata;
    private PlaybackStateCompat mLastPlaybackStateCompat;
    private StraasMediaCore mStraasMediaCore;
    private int mImageButtonBackground;
    private Context mThemeContext;
    private GestureDetectorCompat mGestureDetector, mGestureTapDetector, mGestureFakeDetector;
    private SwitchQualityViewClickListener mSwitchQualityViewListener;
    private ChannelNameMetadataListener mChannelNameMetadataListener = new ChannelNameMetadataListener();
    private SummaryViewerMetadataListener mSummaryViewerMetadataListener = new SummaryViewerMetadataListener();
    private ErrorMessageListener mErrorMessageListener = new ErrorMessageListener();
    private LivePositionTimeListener mLivePositionTimeListener = new LivePositionTimeListener();
    private BroadcastStateListener mBroadcastStateListener = new BroadcastStateListener();

    private List<ConnectionCallback> mMediaConnectedListenerList = new ArrayList<>();
    private SparseArrayCompat<ViewGroup> mCustomColumnList = new SparseArrayCompat<>();
    private List<QueueItem> mLastQueueList;
    private int mUIBroadcastState = BROADCAST_STATE_UNKNOWN;

    public interface SwitchQualityViewClickListener {
        void onFormatCallback(ArrayList<Format> formats, int currentIndex);
    }

    public static final int CUSTOM_COLUMN_TOP_RIGHT = 0;
    public static final int CUSTOM_COLUMN_BOTTOM_LEFT = 1;
    public static final int CUSTOM_COLUMN_BOTTOM_RIGHT1 = 2;
    public static final int CUSTOM_COLUMN_BOTTOM_RIGHT2 = 3;
    public static final int CUSTOM_COLUMN_TOP_RIGHT2 = 4;

    @IntDef({CUSTOM_COLUMN_TOP_RIGHT, CUSTOM_COLUMN_BOTTOM_LEFT, CUSTOM_COLUMN_BOTTOM_RIGHT1,
            CUSTOM_COLUMN_BOTTOM_RIGHT2, CUSTOM_COLUMN_TOP_RIGHT2})
    @Retention(RetentionPolicy.SOURCE)
    public @interface CustomColumnPosition {
    }

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

    public StraasPlayerView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public StraasPlayerView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);

        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.StraasLayout, defStyleAttr, 0);
        getCustomizedAttr(typedArray);
        typedArray.recycle();
    }

    /**
     * Initialize a StrassPlayerView, which can be used to generate layout and control UI.
     *
     * @param fragmentActivity A FragmentActivity which use StraasPlayerView.
     */
    public void initialize(@NonNull FragmentActivity fragmentActivity) {
        initialize(fragmentActivity, null);
    }

    /**
     * Initialize a StrassPlayerView, which can be used to generate layout and control UI.
     *
     * @param fragmentActivity A FragmentActivity which use StraasPlayerView.
     * @param configuration    A configuration for whether default widget to use or not.
     */
    public void initialize(@NonNull FragmentActivity fragmentActivity, @Nullable StraasConfiguration configuration) {

        mFragmentActivity = fragmentActivity;

        if (configuration != null) {
            initConfiguration(configuration);
        }

        init();
    }

    public Context getThemeContext() {
        return mThemeContext;
    }

    private void init() {
        ViewGroup straasMainContainer = (ViewGroup) LayoutInflater.from(getContext())
                .inflate(R.layout.straas_main_container, this, false);
        mThemeContext = straasMainContainer.getContext();
        int[] attr = new int[]{R.attr.selectableItemBackgroundBorderless};
        TypedArray typedArray = mThemeContext.obtainStyledAttributes(attr);
        mImageButtonBackground = Build.VERSION.SDK_INT > 21 ? typedArray.getResourceId(0, 0) : 0;
        typedArray.recycle();

        mControllerContainer = straasMainContainer.findViewById(R.id.controllerContainer);

        straasMainContainer.findViewById(R.id.upContainer).setBackground(
                new GradientDrawable(GradientDrawable.Orientation.BOTTOM_TOP,
                        new int[]{ContextCompat.getColor(mThemeContext, android.R.color.transparent),
                                ContextCompat.getColor(mThemeContext, R.color.color_controller_background_dark)}));
        straasMainContainer.findViewById(R.id.bottomContainer).setBackground(
                new GradientDrawable(GradientDrawable.Orientation.TOP_BOTTOM,
                        new int[]{ContextCompat.getColor(mThemeContext, android.R.color.transparent),
                                ContextCompat.getColor(mThemeContext, R.color.color_controller_background_dark)}));

        mVideoView = straasMainContainer.findViewById(R.id.videoSurfaceView);
        mTextTrack = straasMainContainer.findViewById(R.id.textTrack);
        mImagePoster = new ImageView(getThemeContext());

        initColumn(straasMainContainer);

        mGestureTapDetector = new GestureDetectorCompat(getContext(), new GestureDetector.SimpleOnGestureListener() {
            @Override
            public boolean onSingleTapUp(MotionEvent event) {
                if (!mCanToggleControllerUi) {
                    return false;
                }

                Utils.toggleViewVisibilityWithAnimation(AUTO_HIDE_DELAY_MILLIS, mControllerContainer, mColumnPlayPause);
                return true;
            }

            @Override
            public boolean onDown(MotionEvent e) {
                return true;
            }
        });

        mGestureFakeDetector = new GestureDetectorCompat(getContext(), new GestureDetector.SimpleOnGestureListener());

        if (mEnableDefaultWidget) {
            if (mEnableDefaultSwitchQualityIcon) {
                View switchQualityView = View.inflate(mThemeContext, R.layout.switch_quality_layout, null);
                setSwitchQualityViewPosition(switchQualityView, CUSTOM_COLUMN_TOP_RIGHT);
            }
            if (mEnableDefaultSwitchSpeedIcon) {
                View switchQualityView = View.inflate(mThemeContext, R.layout.switch_speed_layout, null);
                setSwitchSpeedViewPosition(switchQualityView, CUSTOM_COLUMN_TOP_RIGHT2);
            }
            if (mEnableDefaultTextTrackToggle) {
                View textTrackToggleView = View.inflate(mThemeContext, R.layout.text_track_toggle, null);
                setTextTrackToggleViewPosition(textTrackToggleView, CUSTOM_COLUMN_BOTTOM_RIGHT2);
            }
            if (mEnableDefaultChannelName) {
                TextView channelNameTextView = (TextView) View.inflate(mThemeContext, R.layout.channel_name, null);
                setCustomChannelName(channelNameTextView);
            }
            if (mEnableDefaultSummaryViewer) {
                TextView summaryViewerTextView = (TextView) View.inflate(mThemeContext, R.layout.summary_viewer, null);
                TextViewCompat.setCompoundDrawablesRelativeWithIntrinsicBounds(summaryViewerTextView,
                        VectorDrawableCompat.create(getResources(), R.drawable.ic_eye_24dp, null), null, null, null);
                setCustomSummaryViewerView(summaryViewerTextView);
            }
            if (mEnableDefaultLoadingProgressBar) {
                ProgressBar progressBar = (ProgressBar) View.inflate(mThemeContext, R.layout.loading_progress_bar, null);
                setCustomLoadingProgressBar(progressBar);

            }
            if (mEnableDefaultContentSeekBar) {
                ContentSeekBar contentSeekBar = new ContentSeekBar(mThemeContext);
                setCustomContentSeekBar(contentSeekBar);
            }
            if (mEnableDefaultTextTrack) {
                TextView textTrackView = (TextView) View.inflate(mThemeContext, R.layout.text_track, null);
                setCustomTextTrack(textTrackView);
            }
            if (mEnableDefaultPlay) {
                setCustomPlayIcon(R.drawable.ic_play_arrow_48dp);
            }
            if (mEnableDefaultPause) {
                setCustomPauseIcon(R.drawable.ic_pause_48dp);
            }
            if (mEnableDefaultReplay) {
                setCustomReplayIcon(R.drawable.ic_replay_48dp);
            }
            if (mEnableDefaultPrevious) {
                setCustomSkipToPreviousIcon(R.drawable.ic_skip_previous_48dp);
            }
            if (mEnableDefaultNext) {
                setCustomSkipToNextIcon(R.drawable.ic_skip_next_48px);
            }
            if (mEnableDefaultErrorMessage) {
                TextView errorMessageTextView = (TextView) View.inflate(mThemeContext, R.layout.error_message, null);
                Drawable drawable = VectorDrawableCompat.create(getResources(), R.drawable.ic_error_player, null);
                TextViewCompat.setCompoundDrawablesRelativeWithIntrinsicBounds(errorMessageTextView, drawable, null, null, null);
                setCustomErrorMessage(errorMessageTextView);
            }
            if (mEnableDefaultBroadcastStateMessage) {
                View broadcastStateOffline = View.inflate(mThemeContext, R.layout.broadcast_offline, null);
                setCustomBroadcastState(broadcastStateOffline);
            }
        }

        mAdView = straasMainContainer.findViewById(R.id.adSurfaceView);
        addView(straasMainContainer);

        setAutoHideControllerUiWhenTouch(true);
    }

    public void hideControllerViews() {
        mControllerContainer.setVisibility(GONE);
        mColumnPlayPause.setVisibility(GONE);
        mColumnAdPlay.setVisibility(GONE);
        mColumnLoadingBar.setVisibility(GONE);
        mColumnBroadcastState.setVisibility(GONE);
        mColumnErrorMessage.setVisibility(GONE);
    }

    private void initConfiguration(StraasConfiguration configuration) {
        mEnableDefaultWidget = configuration.isEnableDefaultWidget();
        mEnableDefaultSwitchQualityIcon = configuration.isEnableDefaultSwitchQuality();
        mEnableDefaultSwitchSpeedIcon = configuration.isEnableDefaultSwitchSpeed();
        mEnableDefaultTextTrackToggle = configuration.isEnableDefaultTextTrackToggle();
        mEnableDefaultChannelName = configuration.isEnableDefaultChannelName();
        mEnableDefaultSummaryViewer = configuration.isEnableDefaultSummaryViewer();
        mEnableDefaultLoadingProgressBar = configuration.isEnableDefaultLoadingProgressBar();
        mEnableDefaultContentSeekBar = configuration.isEnableDefaultContentProgressBar();
        mEnableDefaultTextTrack = configuration.isEnableDefaultTextTrack();
        mEnableDefaultPlay = configuration.isEnableDefaultPlay();
        mEnableDefaultPause = configuration.isEnableDefaultPause();
        mEnableDefaultReplay = configuration.isEnableDefaultReplay();
        mEnableDefaultPrevious = configuration.isEnableDefaultSkipToPrevious();
        mEnableDefaultNext = configuration.isEnableDefaultSkipToNext();
        mEnableDefaultErrorMessage = configuration.isEnableDefaultErrorMessage();
        mEnableDefaultBroadcastStateMessage = configuration.isEnableDefaultBroadcastStateMessage();
    }

    private final MediaControllerCompat.Callback mMediaControllerCallback = new MediaControllerCompat.Callback() {
        @Override
        public void onQueueChanged(List<QueueItem> queue) {
            mLastQueueList = queue;
            if (mLastQueueList == null) {
                mLastMediaMetadata = null;
                if (mColumnPrevious.getVisibility() != GONE) {
                    mColumnPrevious.setVisibility(GONE);
                }
                if (mColumnNext.getVisibility() != GONE) {
                    mColumnNext.setVisibility(GONE);
                }
            }
        }

        @Override
        public void onSessionDestroyed() {
        }

        @Override
        public void onMetadataChanged(MediaMetadataCompat metadata) {
            if (metadata == null || (mLastMediaMetadata != null &&
                    TextUtils.equals(metadata.getString(MediaMetadataCompat.METADATA_KEY_MEDIA_ID),
                            mLastMediaMetadata.getString(MediaMetadataCompat.METADATA_KEY_MEDIA_ID)) &&
                    TextUtils.equals(metadata.getString(MediaMetadataCompat.METADATA_KEY_DISPLAY_TITLE),
                            mLastMediaMetadata.getString(MediaMetadataCompat.METADATA_KEY_DISPLAY_TITLE)) &&
                    metadata.getBundle().getBoolean(VideoCustomMetadata.CUSTOM_METADATA_IS_LIVE_LOW_LATENCY_FIRST) ==
                            mLastMediaMetadata.getBundle().getBoolean(VideoCustomMetadata.CUSTOM_METADATA_IS_LIVE_LOW_LATENCY_FIRST))) {
                return;
            }

            mLastMediaMetadata = metadata;
            String mediaId = mLastMediaMetadata.getString(MediaMetadataCompat.METADATA_KEY_MEDIA_ID);
            if (TextUtils.isEmpty(mediaId)) {
                return;
            }

            mIsLive = mediaId.startsWith(StraasMediaCore.LIVE_ID_PREFIX);

            if (mLastQueueList != null) {
                if (mLastPlaybackStateCompat.getActiveQueueItemId() == 0) {
                    if (mColumnPrevious.getVisibility() != GONE) {
                        mColumnPrevious.setVisibility(GONE);
                    }
                } else if (mColumnPrevious.getVisibility() != VISIBLE) {
                    mColumnPrevious.setVisibility(VISIBLE);
                }

                if (mLastPlaybackStateCompat.getActiveQueueItemId() == mLastQueueList.size() - 1) {
                    if (mColumnNext.getVisibility() != GONE) {
                        mColumnNext.setVisibility(GONE);
                    }
                } else if (mColumnNext.getVisibility() != VISIBLE) {
                    mColumnNext.setVisibility(VISIBLE);
                }
            }

            String title = metadata.getString(MediaMetadataCompat.METADATA_KEY_DISPLAY_TITLE);
            mChannelNameMetadataListener.onMetaChanged(mChannelNameTextView, title);
        }

        @Override
        public void onCaptioningEnabledChanged(boolean enabled) {
            super.onCaptioningEnabledChanged(enabled);
            if (mTextTrackToggle != null) {
                mTextTrackToggle.setActivated(enabled);
            }
        }

        @Override
        public void onPlaybackStateChanged(PlaybackStateCompat state) {
            if (state == null || (mLastPlaybackStateCompat != null && mLastPlaybackStateCompat.getState() == state.getState() &&
                    mLastPlaybackStateCompat.getActiveQueueItemId() == state.getActiveQueueItemId())) {
                return;
            }
            if (mLastPlaybackStateCompat == null && mTextTrackView != null) {
                MediaControllerCompatHelper.setCaptionEnable(getMediaControllerCompat(), true);
            }
            mLastPlaybackStateCompat = state;
            if (!TextUtils.isEmpty(state.getErrorMessage())) {
                @ErrorReason.ErrorReasonType String errorType = state.getErrorMessage().toString();
                mErrorMessageListener.onError(mErrorMessageTextView, errorType);
                if (mIsLive) {
                    Bundle mediaExtras = (mMediaExtras != null) ? mMediaExtras : getMediaControllerCompat().getExtras();

                    handleBroadcastStateV2(mediaExtras, true);
                }
                if (getKeepScreenOn()) {
                    setKeepScreenOn(false);
                }
                return;
            }

            if (mColumnErrorMessage.getVisibility() != GONE) {
                setErrorMessageVisibility(GONE);
            }

            if (state.getState() == PlaybackStateCompat.STATE_PLAYING) {
                setErrorMessageVisibility(GONE);
                setBroadcastStateVisibility(GONE);
                if (mControllerContainer.getVisibility() != GONE) {
                    Utils.toggleViewVisibilityWithAnimation(AUTO_HIDE_DELAY_MILLIS, mControllerContainer, mColumnPlayPause);
                }
            }

            int loadingProgressBarVisibility = GONE;

            if (state.getActiveQueueItemId() == StraasMediaCore.AD_PLAYBACK_ID) {

                if (mControllerContainer.getVisibility() != GONE) {
                    mControllerContainer.setVisibility(GONE);
                }

                if (mColumnPlayPause.getVisibility() != GONE) {
                    mColumnPlayPause.setVisibility(GONE);
                }

                switch (state.getState()) {
                    case PlaybackStateCompat.STATE_BUFFERING:
                        loadingProgressBarVisibility = VISIBLE;
                        break;
                    case PlaybackStateCompat.STATE_PLAYING:
                        mColumnAdPlay.setVisibility(GONE);
                        mCanToggleControllerUi = false;
                        break;
                    case PlaybackStateCompat.STATE_PAUSED:
                        mColumnAdPlay.setVisibility(VISIBLE);
                        break;
                    case PlaybackStateCompat.STATE_STOPPED:
                        // After AD playing ends, SDK player will seek the live streaming to
                        // the real-time coverage of live automatically for all kinds of live:
                        // normal live, low latency, and live-dvr
                        if (mIsLive) {
                            refreshLiveDvrUiStatus(PLAYBACK_MODE_LIVE_EDGE);
                        }
                        break;
                }
            } else {
                if (mColumnAdPlay.getVisibility() != GONE) {
                    mColumnAdPlay.setVisibility(GONE);
                }

                switch (state.getState()) {
                    case PlaybackStateCompat.STATE_BUFFERING:
                        loadingProgressBarVisibility = VISIBLE;

                        mColumnPlay.setVisibility(GONE);
                        mColumnPause.setVisibility(GONE);
                        break;
                    case PlaybackStateCompat.STATE_PLAYING:
                        mCanToggleControllerUi = true;

                        switchToPause();
                        if (!getKeepScreenOn()) {
                            setKeepScreenOn(true);
                        }
                        break;
                    case PlaybackStateCompat.STATE_PAUSED:
                        if (mPlaybackMode == PLAYBACK_MODE_LIVE_EDGE) {
                            refreshLiveDvrUiStatus(PLAYBACK_MODE_LIVE_DVR);
                        }

                        mCanToggleControllerUi = false;

                        showControllerUi();
                        showPlayUi();
                        if (getKeepScreenOn()) {
                            setKeepScreenOn(false);
                        }
                        break;
                    case PlaybackStateCompat.STATE_NONE:
                        mCanToggleControllerUi = false;
                        hideControllerViews();
                        refreshLiveDvrUiStatus(PLAYBACK_MODE_LIVE_EDGE);
                        if (getKeepScreenOn()) {
                            setKeepScreenOn(false);
                        }
                    case PlaybackStateCompat.STATE_STOPPED:
                        mCanToggleControllerUi = true;
                        if (mIsLive) {
                            Bundle mediaExtras = (mMediaExtras != null) ? mMediaExtras :
                                    getMediaControllerCompat().getExtras();

                            handleBroadcastStateV2(mediaExtras, true);
                        }
                        switchToReplay();
                        if (getKeepScreenOn()) {
                            setKeepScreenOn(false);
                        }
                        break;
                }
            }

            setLoadingProgressBarVisible(loadingProgressBarVisibility == VISIBLE);
        }

        @Override
        public void onSessionEvent(String event, Bundle extras) {
            switch (event) {
                case StraasMediaCore.EVENT_MEDIA_BROWSER_SERVICE_ERROR:
                    mErrorMessageListener.onError(mErrorMessageTextView,
                            extras.getString(StraasMediaCore.KEY_MEDIA_BROWSER_ERROR_REASON));
                    break;
            }
        }

        @Override
        public void onExtrasChanged(Bundle extras) {
            handleTextTrackExtra(extras);

            mMediaExtras = extras;

            if (mIsLive) {
                boolean isLiveSeekable = extras.getBoolean(VideoCustomMetadata.LIVE_DVR_ENABLED) &&
                        !extras.getBoolean(VideoCustomMetadata.CUSTOM_METADATA_IS_LIVE_LOW_LATENCY_FIRST);
                switchMode(true, isLiveSeekable);
                if (isLiveSeekable) {
                    setCustomDvrPlaybackAvailable(View.inflate(mThemeContext, R.layout.dvr_playback_available, null));
                }

                boolean isStopPlay = mLastPlaybackStateCompat != null &&
                        (mLastPlaybackStateCompat.getState() == PlaybackStateCompat.STATE_STOPPED ||
                                mLastPlaybackStateCompat.getState() == PlaybackStateCompat.STATE_NONE ||
                                mLastPlaybackStateCompat.getState() == PlaybackStateCompat.STATE_ERROR);
                handleBroadcastStateV2(extras, isStopPlay);
            } else {
                MediaControllerCompat controller = MediaControllerCompat.getMediaController(mFragmentActivity);
                if (controller != null) {
                    MediaControllerCompatHelper.setPlaybackSpeed(controller, mCurrentSpeed);
                }
                switchMode(false, false);
            }

            long summaryViewer = extras.getLong(VideoCustomMetadata.PLAY_COUNT_SUM);
            mSummaryViewerMetadataListener.onMetaChanged(mSummaryViewerTextView, summaryViewer);

            if (!isPosterAddedIntoVideoContainer()) {
                getVideoContainer().addView(mImagePoster, getVideoContainer().getChildCount());
            }
            if (extras.containsKey(StraasMediaCore.KEY_VIDEO_RENDER_TYPE)
                    && extras.getInt(StraasMediaCore.KEY_VIDEO_RENDER_TYPE) == StraasMediaCore.VIDEO_RENDER_TYPE_NONE) {
                mImagePoster.setVisibility(VISIBLE);
                String albumUri = mLastMediaMetadata != null
                        ? mLastMediaMetadata.getString(MediaMetadataCompat.METADATA_KEY_ALBUM_ART_URI)
                        : null;
                Glide.with(getThemeContext())
                        .setDefaultRequestOptions(new RequestOptions()
                                .placeholder(android.R.color.black))
                        .load(!TextUtils.isEmpty(albumUri)
                                ? albumUri
                                : ContextCompat.getDrawable(mImagePoster.getContext(),
                                R.drawable.vod_thumbnail_audio))
                        .into(mImagePoster);
            } else {
                mImagePoster.setVisibility(GONE);
            }
        }

        private boolean isPosterAddedIntoVideoContainer() {
{'fraction_non_alphanumeric': 0.069829495871652, 'fraction_numerical': 0.002383030140296704, 'mean_word_length': 2.540852100540733, 'pattern_counts': {'":': 0, '<': 17, '<?xml version=': 0, '>': 19, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 6, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '143081', 'n_tokens_mistral': 15556, 'n_tokens_neox': 14801, 'n_words': 2495}