/*
 * 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> {

        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;
    }
}
