/*
 * Copyright (C) 2016 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License
 */

package com.android.tv.dvr.ui.list;

import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.drawable.Drawable;
import androidx.leanback.widget.RowPresenter;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnFocusChangeListener;
import android.view.ViewGroup;
import android.view.animation.DecelerateInterpolator;
import android.widget.TextView;
import com.android.tv.R;
import com.android.tv.TvSingletons;
import com.android.tv.dvr.data.SeriesRecording;
import com.android.tv.dvr.ui.DvrUiHelper;
import com.android.tv.dvr.ui.list.SchedulesHeaderRow.SeriesRecordingHeaderRow;

/** A base class for RowPresenter for {@link SchedulesHeaderRow} */
abstract class SchedulesHeaderRowPresenter extends RowPresenter {
    private Context mContext;

    public SchedulesHeaderRowPresenter(Context context) {
        setHeaderPresenter(null);
        setSelectEffectEnabled(false);
        mContext = context;
    }

    /** Returns the context. */
    Context getContext() {
        return mContext;
    }

    /** A ViewHolder for {@link SchedulesHeaderRow}. */
    public static class SchedulesHeaderRowViewHolder extends RowPresenter.ViewHolder {
        private TextView mTitle;
        private TextView mDescription;

        public SchedulesHeaderRowViewHolder(Context context, ViewGroup parent) {
            super(
                    LayoutInflater.from(context)
                            .inflate(R.layout.dvr_schedules_header, parent, false));
            mTitle = (TextView) view.findViewById(R.id.header_title);
            mDescription = (TextView) view.findViewById(R.id.header_description);
        }
    }

    @Override
    protected void onBindRowViewHolder(RowPresenter.ViewHolder viewHolder, Object item) {
        super.onBindRowViewHolder(viewHolder, item);
        SchedulesHeaderRowViewHolder headerViewHolder = (SchedulesHeaderRowViewHolder) viewHolder;
        SchedulesHeaderRow header = (SchedulesHeaderRow) item;
        headerViewHolder.mTitle.setText(header.getTitle());
        headerViewHolder.mDescription.setText(header.getDescription());
    }

    /** A presenter for {@link SchedulesHeaderRow.DateHeaderRow}. */
    public static class DateHeaderRowPresenter extends SchedulesHeaderRowPresenter {
        public DateHeaderRowPresenter(Context context) {
            super(context);
        }

        @Override
        protected ViewHolder createRowViewHolder(ViewGroup parent) {
            return new DateHeaderRowViewHolder(getContext(), parent);
        }

        /** A ViewHolder for {@link SchedulesHeaderRow.DateHeaderRow}. */
        public static class DateHeaderRowViewHolder extends SchedulesHeaderRowViewHolder {
            public DateHeaderRowViewHolder(Context context, ViewGroup parent) {
                super(context, parent);
            }
        }
    }

    /** A presenter for {@link SeriesRecordingHeaderRow}. */
    public static class SeriesRecordingHeaderRowPresenter extends SchedulesHeaderRowPresenter {
        private final boolean mLtr;
        private final Drawable mSettingsDrawable;
        private final Drawable mCancelDrawable;
        private final Drawable mResumeDrawable;

        private final String mSettingsInfo;
        private final String mCancelAllInfo;
        private final String mResumeInfo;

        public SeriesRecordingHeaderRowPresenter(Context context) {
            super(context);
            mLtr =
                    context.getResources().getConfiguration().getLayoutDirection()
                            == View.LAYOUT_DIRECTION_LTR;
            mSettingsDrawable = context.getDrawable(R.drawable.ic_settings);
            mCancelDrawable = context.getDrawable(R.drawable.ic_dvr_cancel_large);
            mResumeDrawable = context.getDrawable(R.drawable.ic_record_start);
            mSettingsInfo = context.getString(R.string.dvr_series_schedules_settings);
            mCancelAllInfo = context.getString(R.string.dvr_series_schedules_stop);
            mResumeInfo = context.getString(R.string.dvr_series_schedules_start);
        }

        @Override
        protected ViewHolder createRowViewHolder(ViewGroup parent) {
            return new SeriesHeaderRowViewHolder(getContext(), parent);
        }

        @Override
        protected void onBindRowViewHolder(RowPresenter.ViewHolder viewHolder, Object item) {
            super.onBindRowViewHolder(viewHolder, item);
            SeriesHeaderRowViewHolder headerViewHolder = (SeriesHeaderRowViewHolder) viewHolder;
            SeriesRecordingHeaderRow header = (SeriesRecordingHeaderRow) item;
            headerViewHolder.mSeriesSettingsButton.setVisibility(
                    header.getSeriesRecording().isStopped() ? View.INVISIBLE : View.VISIBLE);
            headerViewHolder.mSeriesSettingsButton.setText(mSettingsInfo);
            setTextDrawable(headerViewHolder.mSeriesSettingsButton, mSettingsDrawable);
            if (header.getSeriesRecording().isStopped()) {
                headerViewHolder.mToggleStartStopButton.setText(mResumeInfo);
                setTextDrawable(headerViewHolder.mToggleStartStopButton, mResumeDrawable);
            } else {
                headerViewHolder.mToggleStartStopButton.setText(mCancelAllInfo);
                setTextDrawable(headerViewHolder.mToggleStartStopButton, mCancelDrawable);
            }
            headerViewHolder.mSeriesSettingsButton.setOnClickListener(
                    new OnClickListener() {
                        @Override
                        public void onClick(View view) {
                            DvrUiHelper.startSeriesSettingsActivity(
                                    getContext(),
                                    header.getSeriesRecording().getId(),
                                    header.getPrograms(),
                                    false,
                                    false,
                                    false,
                                    null);
                        }
                    });
            headerViewHolder.mToggleStartStopButton.setOnClickListener(
                    new OnClickListener() {
                        @Override
                        public void onClick(View view) {
                            if (header.getSeriesRecording().isStopped()) {
                                // Reset priority to the highest.
                                SeriesRecording seriesRecording =
                                        SeriesRecording.buildFrom(header.getSeriesRecording())
                                                .setPriority(
                                                        TvSingletons.getSingletons(getContext())
                                                                .getDvrScheduleManager()
                                                                .suggestNewSeriesPriority())
                                                .build();
                                TvSingletons.getSingletons(getContext())
                                        .getDvrManager()
                                        .updateSeriesRecording(seriesRecording);
                                DvrUiHelper.startSeriesSettingsActivity(
                                        getContext(),
                                        header.getSeriesRecording().getId(),
                                        header.getPrograms(),
                                        false,
                                        false,
                                        false,
                                        null);
                            } else {
                                DvrUiHelper.showCancelAllSeriesRecordingDialog(
                                        (DvrSchedulesActivity) view.getContext(),
                                        header.getSeriesRecording());
                            }
                        }
                    });
        }

        private void setTextDrawable(TextView textView, Drawable drawableStart) {
            textView.setCompoundDrawablesRelativeWithIntrinsicBounds(
                    drawableStart, null, null, null);
        }

        /** A ViewHolder for {@link SeriesRecordingHeaderRow}. */
        public static class SeriesHeaderRowViewHolder extends SchedulesHeaderRowViewHolder {
            private final TextView mSeriesSettingsButton;
            private final TextView mToggleStartStopButton;
            private final boolean mLtr;

            private final View mSelector;

            private View mLastFocusedView;

            public SeriesHeaderRowViewHolder(Context context, ViewGroup parent) {
                super(context, parent);
                mLtr =
                        context.getResources().getConfiguration().getLayoutDirection()
                                == View.LAYOUT_DIRECTION_LTR;
                view.findViewById(R.id.button_container).setVisibility(View.VISIBLE);
                mSeriesSettingsButton = (TextView) view.findViewById(R.id.series_settings);
                mToggleStartStopButton =
                        (TextView) view.findViewById(R.id.series_toggle_start_stop);
                mSelector = view.findViewById(R.id.selector);
                OnFocusChangeListener onFocusChangeListener =
                        new View.OnFocusChangeListener() {
                            @Override
                            public void onFocusChange(View view, boolean focused) {
                                view.post(() -> updateSelector(view));
                            }
                        };
                mSeriesSettingsButton.setOnFocusChangeListener(onFocusChangeListener);
                mToggleStartStopButton.setOnFocusChangeListener(onFocusChangeListener);
            }

            private void updateSelector(View focusedView) {
                int animationDuration =
                        mSelector
                                .getContext()
                                .getResources()
                                .getInteger(android.R.integer.config_shortAnimTime);
                DecelerateInterpolator interpolator = new DecelerateInterpolator();

                if (focusedView.hasFocus()) {
                    ViewGroup.LayoutParams lp = mSelector.getLayoutParams();
                    final int targetWidth = focusedView.getWidth();
                    float targetTranslationX;
                    if (mLtr) {
                        targetTranslationX = focusedView.getLeft() - mSelector.getLeft();
                    } else {
                        targetTranslationX = focusedView.getRight() - mSelector.getRight();
                    }

                    // if the selector is invisible, set the width and translation X directly -
                    // don't animate.
                    if (mSelector.getAlpha() == 0) {
                        mSelector.setTranslationX(targetTranslationX);
                        lp.width = targetWidth;
                        mSelector.requestLayout();
                    }

                    // animate the selector in and to the proper width and translation X.
                    final float deltaWidth = lp.width - targetWidth;
                    mSelector.animate().cancel();
                    mSelector
                            .animate()
                            .translationX(targetTranslationX)
                            .alpha(1f)
                            .setUpdateListener(
                                    new ValueAnimator.AnimatorUpdateListener() {
                                        @Override
                                        public void onAnimationUpdate(ValueAnimator animation) {
                                            // Set width to the proper width for this animation
                                            // step.
                                            lp.width =
                                                    targetWidth
                                                            + Math.round(
                                                                    deltaWidth
                                                                            * (1f
                                                                                    - animation
                                                                                            .getAnimatedFraction()));
                                            mSelector.requestLayout();
                                        }
                                    })
                            .setDuration(animationDuration)
                            .setInterpolator(interpolator)
                            .start();
                    mLastFocusedView = focusedView;
                } else if (mLastFocusedView == focusedView) {
                    mSelector.animate().setUpdateListener(null).cancel();
                    mSelector
                            .animate()
                            .alpha(0f)
                            .setDuration(animationDuration)
                            .setInterpolator(interpolator)
                            .start();
                    mLastFocusedView = null;
                }
            }
        }
    }
}
