/*
 * Copyright (C) 2014 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 android.support.v17.leanback.widget;

import android.database.Observable;

/**
 * Base class adapter to be used in leanback activities.  Provides access to a data model and is
 * decoupled from the presentation of the items via {@link PresenterSelector}.
 */
public abstract class ObjectAdapter {

    /** Indicates that an id has not been set. */
    public static final int NO_ID = -1;

    /**
     * A DataObserver can be notified when an ObjectAdapter's underlying data
     * changes. Separate methods provide notifications about different types of
     * changes.
     */
    public static abstract class DataObserver {
        /**
         * Called whenever the ObjectAdapter's data has changed in some manner
         * outside of the set of changes covered by the other range-based change
         * notification methods.
         */
        public void onChanged() {
        }

        /**
         * Called when a range of items in the ObjectAdapter has changed. The
         * basic ordering and structure of the ObjectAdapter has not changed.
         *
         * @param positionStart The position of the first item that changed.
         * @param itemCount The number of items changed.
         */
        public void onItemRangeChanged(int positionStart, int itemCount) {
            onChanged();
        }

        /**
         * Called when a range of items is inserted into the ObjectAdapter.
         *
         * @param positionStart The position of the first inserted item.
         * @param itemCount The number of items inserted.
         */
        public void onItemRangeInserted(int positionStart, int itemCount) {
            onChanged();
        }

        /**
         * Called when a range of items is removed from the ObjectAdapter.
         *
         * @param positionStart The position of the first removed item.
         * @param itemCount The number of items removed.
         */
        public void onItemRangeRemoved(int positionStart, int itemCount) {
            onChanged();
        }
    }

    private static final class DataObservable extends Observable<DataObserver> {

        DataObservable() {
        }

        public void notifyChanged() {
            for (int i = mObservers.size() - 1; i >= 0; i--) {
                mObservers.get(i).onChanged();
            }
        }

        public void notifyItemRangeChanged(int positionStart, int itemCount) {
            for (int i = mObservers.size() - 1; i >= 0; i--) {
                mObservers.get(i).onItemRangeChanged(positionStart, itemCount);
            }
        }

        public void notifyItemRangeInserted(int positionStart, int itemCount) {
            for (int i = mObservers.size() - 1; i >= 0; i--) {
                mObservers.get(i).onItemRangeInserted(positionStart, itemCount);
            }
        }

        public void notifyItemRangeRemoved(int positionStart, int itemCount) {
            for (int i = mObservers.size() - 1; i >= 0; i--) {
                mObservers.get(i).onItemRangeRemoved(positionStart, itemCount);
            }
        }
    }

    private final DataObservable mObservable = new DataObservable();
    private boolean mHasStableIds;
    private PresenterSelector mPresenterSelector;

    /**
     * Constructs an adapter with the given {@link PresenterSelector}.
     */
    public ObjectAdapter(PresenterSelector presenterSelector) {
        setPresenterSelector(presenterSelector);
    }

    /**
     * Constructs an adapter that uses the given {@link Presenter} for all items.
     */
    public ObjectAdapter(Presenter presenter) {
        setPresenterSelector(new SinglePresenterSelector(presenter));
    }

    /**
     * Constructs an adapter.
     */
    public ObjectAdapter() {
    }

    /**
     * Sets the presenter selector.  May not be null.
     */
    public final void setPresenterSelector(PresenterSelector presenterSelector) {
        if (presenterSelector == null) {
            throw new IllegalArgumentException("Presenter selector must not be null");
        }
        final boolean update = (mPresenterSelector != null);
        final boolean selectorChanged = update && mPresenterSelector != presenterSelector;

        mPresenterSelector = presenterSelector;

        if (selectorChanged) {
            onPresenterSelectorChanged();
        }
        if (update) {
            notifyChanged();
        }
    }

    /**
     * Called when {@link #setPresenterSelector(PresenterSelector)} is called
     * and the PresenterSelector differs from the previous one.
     */
    protected void onPresenterSelectorChanged() {
    }

    /**
     * Returns the presenter selector for this ObjectAdapter.
     */
    public final PresenterSelector getPresenterSelector() {
        return mPresenterSelector;
    }

    /**
     * Registers a DataObserver for data change notifications.
     */
    public final void registerObserver(DataObserver observer) {
        mObservable.registerObserver(observer);
    }

    /**
     * Unregisters a DataObserver for data change notifications.
     */
    public final void unregisterObserver(DataObserver observer) {
        mObservable.unregisterObserver(observer);
    }

    /**
     * Unregisters all DataObservers for this ObjectAdapter.
     */
    public final void unregisterAllObservers() {
        mObservable.unregisterAll();
    }

    final protected void notifyItemRangeChanged(int positionStart, int itemCount) {
        mObservable.notifyItemRangeChanged(positionStart, itemCount);
    }

    final protected void notifyItemRangeInserted(int positionStart, int itemCount) {
        mObservable.notifyItemRangeInserted(positionStart, itemCount);
    }

    final protected void notifyItemRangeRemoved(int positionStart, int itemCount) {
        mObservable.notifyItemRangeRemoved(positionStart, itemCount);
    }

    final protected void notifyChanged() {
        mObservable.notifyChanged();
    }

    /**
     * Returns true if the item ids are stable across changes to the
     * underlying data.  When this is true, clients of the ObjectAdapter can use
     * {@link #getId(int)} to correlate Objects across changes.
     */
    public final boolean hasStableIds() {
        return mHasStableIds;
    }

    /**
     * Sets whether the item ids are stable across changes to the underlying
     * data.
     */
    public final void setHasStableIds(boolean hasStableIds) {
        boolean changed = mHasStableIds != hasStableIds;
        mHasStableIds = hasStableIds;

        if (changed) {
            onHasStableIdsChanged();
        }
    }

    /**
     * Called when {@link #setHasStableIds(boolean)} is called and the status
     * of stable ids has changed.
     */
    protected void onHasStableIdsChanged() {
    }

    /**
     * Returns the {@link Presenter} for the given item from the adapter.
     */
    public final Presenter getPresenter(Object item) {
        if (mPresenterSelector == null) {
            throw new IllegalStateException("Presenter selector must not be null");
        }
        return mPresenterSelector.getPresenter(item);
    }

    /**
     * Returns the number of items in the adapter.
     */
    public abstract int size();

    /**
     * Returns the item for the given position.
     */
    public abstract Object get(int position);

    /**
     * Returns the id for the given position.
     */
    public long getId(int position) {
        return NO_ID;
    }

    /**
     * Returns true if the adapter pairs each underlying data change with a call to notify and
     * false otherwise.
     */
    public boolean isImmediateNotifySupported() {
        return false;
    }
}
