/*
 *    Copyright 2010 Chris Sinjakli
 *
 * 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.
 */

/**
 * @author Chris Sinjakli
 */
package uk.co.sinjakli.trivial;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Random;
import java.util.concurrent.CancellationException;
import java.util.concurrent.ExecutionException;

import android.app.Activity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.widget.Toast;


public class QuizActivity extends Activity {
	
	// Private Constants
	private static final String TAG = "QuizActivity";
	
	// Private member variables
	private ArrayList<Question> questions;
	private long seed;
	
	/**
	 * Sets up the initial state of the QuizActivity by loading the questions from the asset files.
	 * 
	 * @param savedInstanceState Any state which was saved about an ongoing quiz at an earlier time.
	 */
	@Override
	public void onCreate(final Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		final AsyncTask<String,Integer,ArrayList<Question>> task = new LoadQuestionsTask().execute("questions/");
		try {
			questions = task.get();
		} catch (final InterruptedException e) {
			Log.e(TAG, "InterruptedException while attempting to load questions using LoadQuestionsTask.", e); // Dev String
			Toast.makeText(getApplicationContext(), getResources().getString(R.string.question_reading_exception), Toast.LENGTH_LONG).show();
		} catch (final ExecutionException e) {
			Log.e(TAG, "ExcecutionException while attempting to load questions using LoadQuestionsTask.", e); // Dev String
			Toast.makeText(getApplicationContext(), getResources().getString(R.string.question_reading_exception), Toast.LENGTH_LONG).show();
		} catch (final CancellationException e) {
			Log.e(TAG, "CancellationException while attempting to load questions using LoadQuestionsTask.", e); // Dev String
			Toast.makeText(getApplicationContext(), getResources().getString(R.string.question_reading_exception), Toast.LENGTH_LONG).show();
		}
		
		// If no questions were loaded, close the Activity
		if (null == questions) {
			this.finish();
		}

		// Either load the seed if it has been stored, or create one and store it if it hasn't

		if (null != savedInstanceState && savedInstanceState.containsKey("seed")) {
			seed = savedInstanceState.getLong("seed");
		} else {
			seed = new Random().nextLong();
		}
		
		// Randomise the output order of the questions
		final Random rand = new Random(seed);
		Collections.shuffle(questions, rand);
	}
	
	@Override
	protected void onStart() {
		super.onStart();
	}
	
	@Override
	protected void onSaveInstanceState(Bundle outState) {
		outState.putLong("seed", seed);
		super.onSaveInstanceState(outState);
	}

	/**
	 * Loads questions stored in all files at the specified file path. Returns an empty {@link ArrayList} if there are no questions found.
	 * 
	 * @param questionFilePath The file path from which questions should be loaded.
	 * @return An {@link ArrayList} of all questions found at the specified path.
	 */
	private ArrayList<Question> loadQuestions(final String questionFilePath) {
		final ArrayList<Question> questions = new ArrayList<Question>();
		try {
			int failedParsesTotal = 0;
			for (final String fileName : getAssets().list(questionFilePath)) {
				final InputStream input = getAssets().open(questionFilePath + fileName);
				final BufferedReader reader = new BufferedReader(new InputStreamReader(input));
				
				// Populate the questions ArrayList
				String inputLine;
				int failedParses = 0;
				while (null != (inputLine = reader.readLine())) {
					// Ignore any comments in the question file
					if (!inputLine.startsWith("//")) {
						try {
							questions.add(Question.parse(inputLine));
						} catch (final IllegalArgumentException e) {
							failedParses++;
							Log.e(TAG, "Unable to parse question: " + inputLine, e); // Dev String
						}
					}
				}
				
				// If any questions failed to parse within the current file, summarise how many failed
				if (0 < failedParses) {
					failedParsesTotal += failedParses;
					Log.e(TAG, failedParses + " questions were unable to be parsed in file " + questionFilePath + fileName); // Dev String
				}
			}
			
			// If any questions failed to parse within any file, summarise (to the user) how many failed
			if (0 < failedParsesTotal) {
				Toast.makeText(getApplicationContext(), String.format(getResources().getQuantityString(R.plurals.question_reading_parse_fail_number, failedParsesTotal), failedParsesTotal), Toast.LENGTH_LONG).show();
			}
			
		} catch (final IOException e) {
			Log.e(TAG, "Error reading questions.", e); // Dev String
			Toast.makeText(getApplicationContext(), getResources().getString(R.string.question_reading_exception), Toast.LENGTH_LONG).show();
		}
		
		return questions;
	}
	
	private class LoadQuestionsTask extends AsyncTask<String, Integer, ArrayList<Question>> {
		
		// TODO: Move some of the logic from loadQuestion into here. loadQuestion should just deal with an individual file.
		@Override
		protected ArrayList<Question> doInBackground(String... params) {
			ArrayList<Question> questions = new ArrayList<Question>();
			
			// Load all questions available at each path given as an argument
			for (String path : params) {
				questions.addAll(loadQuestions(path));
			}
			return questions;
		}
		
	}
}
@@ -1363,16 +1363,39 @@
  seed;%0D%0A
+%09int currentQuestion;%0D%0A
 %09%0D%0A%09/**%0D
@@ -3026,16 +3026,69 @@
 (%22seed%22)
+ && savedInstanceState.containsKey(%22currentQuestion%22)
 ) %7B%0D%0A%09%09%09
@@ -3127,24 +3127,92 @@
 g(%22seed%22);%0D%0A
+%09%09%09currentQuestion = savedInstanceState.getInt(%22currentQuestion%22);%0D%0A
 %09%09%7D else %7B%0D%0A
@@ -3243,24 +3243,49 @@
 extLong();%0D%0A
+%09%09%09currentQuestion = 0;%0D%0A
 %09%09%7D%0D%0A%09%09%0D%0A%09%09/
@@ -3591,16 +3591,72 @@
 seed);%0D%0A
+%09%09outState.putInt(%22currentQuestion%22, currentQuestion);%0D%0A
 %09%09super.

Save and restore the current question.