/*
 * Copyright (C) 2015 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.messaging.ui;

import android.os.Bundle;
import android.os.Parcelable;
import androidx.viewpager.widget.PagerAdapter;
import android.view.View;
import android.view.ViewGroup;

import com.android.messaging.Factory;
import com.android.messaging.util.Assert;
import com.android.messaging.util.UiUtils;
import com.google.common.annotations.VisibleForTesting;

/**
 * A PagerAdapter that provides a fixed number of paged Views provided by a fixed set of
 * {@link PagerViewHolder}'s. This allows us to put a fixed number of Views, instead of fragments,
 * into a given ViewPager.
 */
public class FixedViewPagerAdapter<T extends PagerViewHolder> extends PagerAdapter {
    private final T[] mViewHolders;

    public FixedViewPagerAdapter(final T[] viewHolders) {
        Assert.notNull(viewHolders);
        mViewHolders = viewHolders;
    }

    @Override
    public Object instantiateItem(final ViewGroup container, final int position) {
        final PagerViewHolder viewHolder = getViewHolder(position);
        final View view = viewHolder.getView(container);
        if (view == null) {
            return null;
        }
        view.setTag(viewHolder);
        container.addView(view);
        return viewHolder;
    }

    @Override
    public void destroyItem(final ViewGroup container, final int position, final Object object) {
        final PagerViewHolder viewHolder = getViewHolder(position);
        final View destroyedView = viewHolder.destroyView();
        if (destroyedView != null) {
            container.removeView(destroyedView);
        }
    }

    @Override
    public int getCount() {
        return mViewHolders.length;
    }

    @Override
    public boolean isViewFromObject(final View view, final Object object) {
        return view.getTag() == object;
    }

    public T getViewHolder(final int i) {
        return getViewHolder(i, true /* rtlAware */);
    }

    @VisibleForTesting
    public T getViewHolder(final int i, final boolean rtlAware) {
        return mViewHolders[rtlAware ? getRtlPosition(i) : i];
    }

    @Override
    public Parcelable saveState() {
        // The paged views in the view pager gets created and destroyed as the user scrolls through
        // them. By default, only the pages to the immediate left and right of the current visible
        // page are realized. Moreover, if the activity gets destroyed and recreated, the pages are
        // automatically destroyed. Therefore, in order to preserve transient page UI states that
        // are not persisted in the DB we'd like to store them in a Bundle when views get
        // destroyed. When the views get recreated, we rehydrate them by passing them the saved
        // data. When the activity gets destroyed, it invokes saveState() on this adapter to
        // add this saved Bundle to the overall saved instance state.
        final Bundle savedViewHolderState = new Bundle(Factory.get().getApplicationContext()
                .getClassLoader());
        for (int i = 0; i < mViewHolders.length; i++) {
            final Parcelable pageState = getViewHolder(i).saveState();
            savedViewHolderState.putParcelable(getInstanceStateKeyForPage(i), pageState);
        }
        return savedViewHolderState;
    }

    @Override
    public void restoreState(final Parcelable state, final ClassLoader loader) {
        if (state instanceof Bundle) {
            final Bundle restoredViewHolderState = (Bundle) state;
            ((Bundle) state).setClassLoader(Factory.get().getApplicationContext().getClassLoader());
            for (int i = 0; i < mViewHolders.length; i++) {
                final Parcelable pageState = restoredViewHolderState
                        .getParcelable(getInstanceStateKeyForPage(i));
                getViewHolder(i).restoreState(pageState);
            }
        } else {
            super.restoreState(state, loader);
        }
    }

    public void resetState() {
        for (int i = 0; i < mViewHolders.length; i++) {
            getViewHolder(i).resetState();
        }
    }

    private String getInstanceStateKeyForPage(final int i) {
        return getViewHolder(i).getClass().getCanonicalName() + "_savedstate_" + i;
    }

    protected int getRtlPosition(final int position) {
        if (UiUtils.isRtlMode()) {
            return mViewHolders.length - 1 - position;
        }
        return position;
    }
}
