1/*
2 * Copyright (C) 2013 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.camera.data;
18
19import android.content.Context;
20import android.net.Uri;
21import android.os.AsyncTask;
22import android.view.View;
23
24import com.android.camera.data.FilmstripItem.VideoClickedCallback;
25import com.android.camera.debug.Log;
26import com.android.camera.filmstrip.FilmstripDataAdapter;
27import com.google.common.base.Optional;
28
29/**
30 * A {@link LocalFilmstripDataAdapter} which puts a {@link FilmstripItem} fixed at the first
31 * position. It's done by combining a {@link FilmstripItem} and another
32 * {@link LocalFilmstripDataAdapter}.
33 */
34public class FixedFirstProxyAdapter extends FilmstripDataAdapterProxy
35        implements FilmstripDataAdapter.Listener {
36    @SuppressWarnings("unused")
37    private static final Log.Tag TAG = new Log.Tag("FixedFirstDataAdpt");
38
39    private FilmstripItem mFirstData;
40    private Listener mListener;
41
42    /**
43     * Constructor.
44     *
45     * @param context Valid Android context.
46     * @param wrappedAdapter The {@link LocalFilmstripDataAdapter} to be wrapped.
47     * @param firstData The {@link FilmstripItem} to be placed at the first
48     *            position.
49     */
50    public FixedFirstProxyAdapter(
51          Context context,
52          LocalFilmstripDataAdapter wrappedAdapter,
53          FilmstripItem firstData) {
54        super(context, wrappedAdapter);
55        if (firstData == null) {
56            throw new AssertionError("data is null");
57        }
58        mFirstData = firstData;
59    }
60
61    @Override
62    public FilmstripItem getItemAt(int index) {
63        if (index == 0) {
64            return mFirstData;
65        }
66        return mAdapter.getItemAt(index - 1);
67    }
68
69    @Override
70    public void removeAt(int index) {
71        if (index > 0) {
72            mAdapter.removeAt(index - 1);
73        }
74    }
75
76    @Override
77    public int findByContentUri(Uri uri) {
78        int pos = mAdapter.findByContentUri(uri);
79        if (pos != -1) {
80            return pos + 1;
81        }
82        return -1;
83    }
84
85    @Override
86    public void updateItemAt(int pos, FilmstripItem item) {
87        if (pos == 0) {
88            mFirstData = item;
89            if (mListener != null) {
90                mListener.onFilmstripItemUpdated(new UpdateReporter() {
91                    @Override
92                    public boolean isDataRemoved(int index) {
93                        return false;
94                    }
95
96                    @Override
97                    public boolean isDataUpdated(int index) {
98                        return (index == 0);
99                    }
100                });
101            }
102        } else {
103            mAdapter.updateItemAt(pos - 1, item);
104        }
105    }
106
107    @Override
108    public int getTotalNumber() {
109        return (mAdapter.getTotalNumber() + 1);
110    }
111
112    @Override
113    public View getView(View recycled, int index, VideoClickedCallback videoClickedCallback) {
114        if (index == 0) {
115            mFirstData.setSuggestedSize(mSuggestedWidth, mSuggestedHeight);
116            return mFirstData.getView(Optional.fromNullable(recycled), null, false,
117                  videoClickedCallback);
118        }
119        return mAdapter.getView(recycled, index - 1, videoClickedCallback);
120    }
121
122    @Override
123    public int getItemViewType(int index) {
124        if (index == 0) {
125            return mFirstData.getItemViewType().ordinal();
126        }
127        return mAdapter.getItemViewType(index);
128    }
129
130    @Override
131    public FilmstripItem getFilmstripItemAt(int index) {
132        if (index == 0) {
133            return mFirstData;
134        }
135        return mAdapter.getFilmstripItemAt(index - 1);
136    }
137
138    @Override
139    public void setListener(Listener listener) {
140        mListener = listener;
141        mAdapter.setListener((listener == null) ? null : this);
142        // The first data is always there. Thus, When the listener is set,
143        // we should call listener.onFilmstripItemLoaded().
144        if (mListener != null) {
145            mListener.onFilmstripItemLoaded();
146        }
147    }
148
149    @Override
150    public void onFilmstripItemLoaded() {
151        if (mListener == null) {
152            return;
153        }
154        mListener.onFilmstripItemUpdated(new UpdateReporter() {
155            @Override
156            public boolean isDataRemoved(int index) {
157                return false;
158            }
159
160            @Override
161            public boolean isDataUpdated(int index) {
162                return (index != 0);
163            }
164        });
165    }
166
167    @Override
168    public void onFilmstripItemUpdated(final UpdateReporter reporter) {
169        mListener.onFilmstripItemUpdated(new UpdateReporter() {
170            @Override
171            public boolean isDataRemoved(int index) {
172                return (index != 0) && reporter.isDataRemoved(index - 1);
173            }
174
175            @Override
176            public boolean isDataUpdated(int index) {
177                return (index != 0) && reporter.isDataUpdated(index - 1);
178            }
179        });
180    }
181
182    @Override
183    public void onFilmstripItemInserted(int index, FilmstripItem item) {
184        mListener.onFilmstripItemInserted(index + 1, item);
185    }
186
187    @Override
188    public void onFilmstripItemRemoved(int index, FilmstripItem item) {
189        mListener.onFilmstripItemRemoved(index + 1, item);
190    }
191
192    @Override
193    public AsyncTask updateMetadataAt(int index) {
194        if (index > 0) {
195            return mAdapter.updateMetadataAt(index - 1);
196        } else {
197            MetadataLoader.loadMetadata(mContext, mFirstData);
198        }
199        return null;
200    }
201
202    @Override
203    public boolean isMetadataUpdatedAt(int index) {
204        if (index > 0) {
205            return mAdapter.isMetadataUpdatedAt(index - 1);
206        } else {
207            return mFirstData.getMetadata().isLoaded();
208        }
209    }
210}
211