1/*
2 * Copyright (C) 2010 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.replica.replicaisland;
18
19import android.app.ListActivity;
20import android.content.Context;
21import android.content.Intent;
22import android.media.AudioManager;
23import android.os.Bundle;
24import android.view.KeyEvent;
25import android.view.LayoutInflater;
26import android.view.Menu;
27import android.view.MenuItem;
28import android.view.View;
29import android.view.ViewGroup;
30import android.view.animation.Animation;
31import android.view.animation.AnimationUtils;
32import android.widget.ArrayAdapter;
33import android.widget.ListView;
34import android.widget.TextView;
35
36import java.lang.reflect.InvocationTargetException;
37import java.util.ArrayList;
38import java.util.Comparator;
39import java.util.List;
40
41public class LevelSelectActivity extends ListActivity {
42    private final static int UNLOCK_ALL_LEVELS_ID = 0;
43    private final static int UNLOCK_NEXT_LEVEL_ID = 1;
44    private final static LevelDataComparator sLevelComparator = new LevelDataComparator();
45    private ArrayList<LevelMetaData> mLevelData;
46    private Animation mButtonFlickerAnimation;
47    private boolean mLevelSelected;
48
49    private class LevelMetaData {
50        public LevelTree.Level level;
51        public int x;
52        public int y;
53        boolean enabled;
54
55        @Override
56        public String toString() {
57            return level.name;
58        }
59    }
60
61    private class DisableItemArrayAdapter<T> extends ArrayAdapter<T> {
62    	private static final int TYPE_ENABLED = 0;
63    	private static final int TYPE_DISABLED = 1;
64    	private static final int TYPE_COMPLETED = 2;
65    	private static final int TYPE_COUNT = 3;
66
67        private int mRowResource;
68        private int mDisabledRowResource;
69        private int mCompletedRowResource;
70        private Context mContext;
71        private int mTextViewResource;
72        private int mTextViewResource2;
73
74        public DisableItemArrayAdapter(Context context, int resource, int disabledResource, int completedResource,
75                int textViewResourceId, int textViewResourceId2, List<T> objects) {
76            super(context, resource, textViewResourceId, objects);
77            mRowResource = resource;
78            mDisabledRowResource = disabledResource;
79            mCompletedRowResource = completedResource;
80            mContext = context;
81            mTextViewResource = textViewResourceId;
82            mTextViewResource2 = textViewResourceId2;
83        }
84
85        @Override
86        public boolean isEnabled(int position) {
87            // TODO: do we have separators in this list?
88            return mLevelData.get(position).enabled;
89        }
90
91
92        @Override
93		public boolean areAllItemsEnabled() {
94			return false;
95		}
96
97		@Override
98		public int getItemViewType(int position) {
99			int type = TYPE_ENABLED;
100			LevelMetaData level = mLevelData.get(position);
101			if (level != null) {
102				if (!level.enabled) {
103					if (level.level.completed) {
104						type = TYPE_COMPLETED;
105					} else {
106						type = TYPE_DISABLED;
107					}
108				}
109			}
110			return type;
111		}
112
113		@Override
114		public int getViewTypeCount() {
115			return TYPE_COUNT;
116		}
117
118		@Override
119		public boolean hasStableIds() {
120			return true;
121		}
122
123		@Override
124		public boolean isEmpty() {
125			return mLevelData.size() > 0;
126		}
127
128		@Override
129        public View getView (int position, View convertView, ViewGroup parent) {
130            View sourceView = null;
131            if (mLevelData.get(position).enabled) {
132            	if (convertView != null && convertView.getId() == mRowResource) {
133            		sourceView = convertView;
134            	} else {
135            		sourceView = LayoutInflater.from(mContext).inflate(
136            				mRowResource, parent, false);
137            	}
138            } else if (mLevelData.get(position).level.completed) {
139            	if (convertView != null && convertView.getId() == mCompletedRowResource) {
140            		sourceView = convertView;
141            	} else {
142            		sourceView = LayoutInflater.from(mContext).inflate(
143            				mCompletedRowResource, parent, false);
144            	}
145            } else {
146            	if (convertView != null && convertView.getId() == mDisabledRowResource) {
147            		sourceView = convertView;
148            	} else {
149            		sourceView = LayoutInflater.from(mContext).inflate(
150                        mDisabledRowResource, parent, false);
151            	}
152            }
153            TextView view = (TextView)sourceView.findViewById(mTextViewResource);
154            if (view != null) {
155                view.setText(mLevelData.get(position).level.name);
156            }
157
158            TextView view2 = (TextView)sourceView.findViewById(mTextViewResource2);
159            if (view2 != null) {
160                view2.setText(mLevelData.get(position).level.timeStamp);
161            }
162            return sourceView;
163        }
164
165    }
166
167    /** Called when the activity is first created. */
168    @Override
169    public void onCreate(Bundle savedInstanceState) {
170        super.onCreate(savedInstanceState);
171        setContentView(R.layout.level_select);
172        mLevelData = new ArrayList<LevelMetaData>();
173
174        if (getIntent().getBooleanExtra("unlockAll", false)) {
175        	generateLevelList(false);
176        	for (LevelMetaData level : mLevelData) {
177                level.enabled = true;
178            }
179        } else {
180        	generateLevelList(true);
181        }
182
183
184        DisableItemArrayAdapter<LevelMetaData> adapter = new DisableItemArrayAdapter<LevelMetaData>(
185                this, R.layout.level_select_row, R.layout.level_select_disabled_row, R.layout.level_select_completed_row,
186                R.id.title, R.id.time, mLevelData);
187
188        adapter.sort(sLevelComparator);
189
190        setListAdapter(adapter);
191
192        mButtonFlickerAnimation = AnimationUtils.loadAnimation(this, R.anim.button_flicker);
193
194        mLevelSelected = false;
195
196        // Keep the volume control type consistent across all activities.
197        setVolumeControlStream(AudioManager.STREAM_MUSIC);
198    }
199
200    protected void generateLevelList(boolean onlyAllowThePast) {
201    	final int count = LevelTree.levels.size();
202        boolean oneBranchUnlocked = false;
203        for (int x = 0; x < count; x++) {
204            boolean anyUnlocksThisBranch = false;
205            final LevelTree.LevelGroup group = LevelTree.levels.get(x);
206            for (int y = 0; y < group.levels.size(); y++) {
207                LevelTree.Level level = group.levels.get(y);
208                boolean enabled = false;
209                if (!level.completed && !oneBranchUnlocked) {
210                    enabled = true;
211                    anyUnlocksThisBranch = true;
212                }
213                if (enabled || level.completed || !onlyAllowThePast || (onlyAllowThePast && level.inThePast)) {
214                	addItem(level, x, y, enabled);
215                }
216            }
217            if (anyUnlocksThisBranch) {
218                oneBranchUnlocked = true;
219            }
220        }
221    }
222
223    protected void unlockNext() {
224    	final int count = LevelTree.levels.size();
225        for (int x = 0; x < count; x++) {
226            final LevelTree.LevelGroup group = LevelTree.levels.get(x);
227            for (int y = 0; y < group.levels.size(); y++) {
228                LevelTree.Level level = group.levels.get(y);
229                if (!level.completed) {
230                	level.completed = true;
231                    return;
232                }
233            }
234
235        }
236    }
237
238
239    @Override
240    protected void onListItemClick(ListView l, View v, int position, long id) {
241        if (!mLevelSelected) {
242	        super.onListItemClick(l, v, position, id);
243	        LevelMetaData selectedLevel = mLevelData.get(position);
244	        if (selectedLevel.enabled) {
245	        	mLevelSelected = true;
246	            Intent intent = new Intent();
247
248	            intent.putExtra("resource", selectedLevel.level.resource);
249	            intent.putExtra("row", selectedLevel.x);
250	            intent.putExtra("index", selectedLevel.y);
251	            TextView text = (TextView)v.findViewById(R.id.title);
252	            if (text != null) {
253	            	text.startAnimation(mButtonFlickerAnimation);
254	            	mButtonFlickerAnimation.setAnimationListener(new EndActivityAfterAnimation(intent));
255	            } else {
256	                setResult(RESULT_OK, intent);
257	            	finish();
258	            	if (UIConstants.mOverridePendingTransition != null) {
259		 		       try {
260		 		    	  UIConstants.mOverridePendingTransition.invoke(LevelSelectActivity.this, R.anim.activity_fade_in, R.anim.activity_fade_out);
261		 		       } catch (InvocationTargetException ite) {
262		 		           DebugLog.d("Activity Transition", "Invocation Target Exception");
263		 		       } catch (IllegalAccessException ie) {
264		 		    	   DebugLog.d("Activity Transition", "Illegal Access Exception");
265		 		       }
266		            }
267	            }
268	        }
269        }
270    }
271
272    private void addItem(LevelTree.Level level, int x, int y, boolean enabled) {
273        LevelMetaData data = new LevelMetaData();
274        data.level = level;
275        data.x = x;
276        data.y = y;
277        data.enabled = enabled;
278        mLevelData.add(data);
279    }
280
281    @Override
282    public boolean onCreateOptionsMenu(Menu menu) {
283        super.onCreateOptionsMenu(menu);
284        boolean handled = false;
285        if (AndouKun.VERSION < 0) {
286        	menu.add(0, UNLOCK_NEXT_LEVEL_ID, 0, R.string.unlock_next_level);
287        	menu.add(0, UNLOCK_ALL_LEVELS_ID, 0, R.string.unlock_levels);
288
289        	handled = true;
290        }
291        return handled;
292    }
293
294    @Override
295    public boolean onMenuItemSelected(int featureId, MenuItem item) {
296        switch(item.getItemId()) {
297        case UNLOCK_NEXT_LEVEL_ID:
298        	unlockNext();
299        	mLevelData.clear();
300        	generateLevelList(false);
301            ((ArrayAdapter)getListAdapter()).sort(sLevelComparator);
302            ((ArrayAdapter)getListAdapter()).notifyDataSetChanged();
303
304        	return true;
305
306        case UNLOCK_ALL_LEVELS_ID:
307        	// Regenerate the level list to remove the past-only filter.
308        	mLevelData.clear();
309        	generateLevelList(false);
310            for (LevelMetaData level : mLevelData) {
311                level.enabled = true;
312            }
313
314            ((ArrayAdapter)getListAdapter()).sort(sLevelComparator);
315            ((ArrayAdapter)getListAdapter()).notifyDataSetChanged();
316            return true;
317        }
318
319        return super.onMenuItemSelected(featureId, item);
320    }
321
322
323    @Override
324	public boolean onKeyDown(int keyCode, KeyEvent event) {
325    	boolean result = false;
326		if (keyCode == KeyEvent.KEYCODE_BACK) {
327			result = true;
328		}
329		return result;
330	}
331
332	@Override
333	public boolean onKeyUp(int keyCode, KeyEvent event) {
334		boolean result = false;
335		if (keyCode == KeyEvent.KEYCODE_BACK) {
336			result = true;
337		}
338		return result;
339	}
340
341
342	/** Comparator for level meta data. */
343    private final static class LevelDataComparator implements Comparator<LevelMetaData> {
344        public int compare(final LevelMetaData object1, final LevelMetaData object2) {
345            int result = 0;
346            if (object1 == null && object2 != null) {
347                result = 1;
348            } else if (object1 != null && object2 == null) {
349                result = -1;
350            } else if (object1 != null && object2 != null) {
351                result = object1.level.timeStamp.compareTo(object2.level.timeStamp);
352            }
353            return result;
354        }
355    }
356
357    protected class EndActivityAfterAnimation implements Animation.AnimationListener {
358        private Intent mIntent;
359
360        EndActivityAfterAnimation(Intent intent) {
361            mIntent = intent;
362        }
363
364
365        public void onAnimationEnd(Animation animation) {
366            setResult(RESULT_OK, mIntent);
367            finish();
368        }
369
370        public void onAnimationRepeat(Animation animation) {
371            // TODO Auto-generated method stub
372
373        }
374
375        public void onAnimationStart(Animation animation) {
376            // TODO Auto-generated method stub
377
378        }
379
380    }
381}
382
383