package com.example.wordbook;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.TimeUnit;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
import android.text.Html;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.RatingBar;
import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;
import android.widget.TextView;

import com.example.wordbook.common.Common;
import com.example.wordbook.common.DBAccess;
import com.example.wordbook.common.Data;
import com.example.wordbook.common.DataManager;

/**
 * 詳細画面クラス
 */
public class DetailActivity extends Activity {

	/** TAG */
	private static final String TAG = DetailActivity.class.getSimpleName();

	/** フラグ選択ダイアログ */
	private static final int DIALOG_FLAG = 1;
	/** メモ編集ダイアログ */
	private static final int DIALOG_EDIT = 2;
	/** 試験結果ダイアログ */
	private static final int DIALOG_RESULT = 5;
	/** 位置指定ダイアログ */
	private static final int DIALOG_SEEK = 6;

	/** インスタンス状態用キー */
	private static final String IS_DATA = "data";

	/** 単語帳DBデータインデックス */
	private int mIndex;
	/** 単語帳DBデータ項目数 */
	private int mCount;

	/** 出題方法 */
	private int mMode;
	/** 出題順序 */
	private int mSort;
	/** 試験単位 */
	private int mSuite;
	/** アイコン位置 */
	private int mIcon;

	/** データ管理クラス */
	private DataManager mDM = new DataManager();

	/** Level rating bar */
	private RatingBar mRateLv;
	/** Number text field */
	private TextView mTxtNo;
	/** Question text field */
	private TextView mTxtQ;
	/** Answer text field */
	private TextView mTxtA;
	/** Data text field */
	private TextView mTxtD;
	/** Before view */
	private View mViewBefore;
	/** After view */
	private View mViewAfter;

	/** ExecutorService */
	private ExecutorService mES;

	/*
	 * (非 Javadoc)
	 * 
	 * @see android.app.Activity#onCreate(android.os.Bundle)
	 */
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		Log.d(TAG, "onCreate()");

		// 単語帳DBデータ情報取得
		int base = 0;
		String title = "";
		Bundle ext = getIntent().getExtras();
		if (ext == null) {
			Log.w(TAG, "onCreate() Intent==null");
			finish();
		} else {
			mIndex = ext.getInt(Common.INTENT_INDEX, 0);
			mCount = ext.getInt(Common.INTENT_COUNT, 0);
			base = ext.getInt(Common.INTENT_BASE, 0);
			title = ext.getString(Common.INTENT_TITLE);
		}
		Log.d(TAG, "index=" + mIndex + "/count=" + mCount + "/base=" + base
				+ "/title=" + title);

		// 設定取得
		mMode = Common.getMode(getApplicationContext());
		mSort = Common.getSort(getApplicationContext());
		mSuite = Common.getSuite(getApplicationContext());
		mIcon = Common.getIcon(getApplicationContext());

		// 状態復帰
		if (savedInstanceState != null) {
			mDM = (DataManager) savedInstanceState.getSerializable(IS_DATA);
		} else {
			mDM.init(base);
		}
		Log.d(TAG, "size=" + mDM.getDataList().size());

		// レイアウト設定
		setContentView(R.layout.detail);
		// タイトル設定
		setTitle(title);

		// アイコン用イベントリスナ設定
		final ImageView imgFlag = (ImageView) findViewById(R.id.imageViewFlag);
		imgFlag.setOnClickListener(new View.OnClickListener() {
			@Override
			public void onClick(View view) {
				doClickFlag(view);
			}
		});
		final ImageView imgEdit = (ImageView) findViewById(R.id.imageViewEdit);
		imgEdit.setOnClickListener(new View.OnClickListener() {
			@Override
			public void onClick(View view) {
				doClickEdit(view);
			}
		});
		final ImageView imgSound = (ImageView) findViewById(R.id.imageViewSound);
		imgSound.setOnClickListener(new View.OnClickListener() {
			@Override
			public void onClick(View view) {
				doClickSound(view);
			}
		});
		final ImageView imgLink = (ImageView) findViewById(R.id.imageViewLink);
		imgLink.setOnClickListener(new View.OnClickListener() {
			@Override
			public void onClick(View view) {
				doClickLink(view);
			}
		});

		// ボタン用イベントリスナ設定
		final Button btnChk = (Button) findViewById(R.id.buttonCheck);
		btnChk.setOnClickListener(new View.OnClickListener() {
			@Override
			public void onClick(View view) {
				doClickCheck();
			}
		});
		final Button btnNG = (Button) findViewById(R.id.buttonNG);
		btnNG.setOnClickListener(new View.OnClickListener() {
			@Override
			public void onClick(View view) {
				doClickNG();
			}
		});
		final Button btnOK = (Button) findViewById(R.id.buttonOK);
		btnOK.setOnClickListener(new View.OnClickListener() {
			@Override
			public void onClick(View view) {
				doClickOK();
			}
		});

		// 表示用ビュー取得
		mRateLv = (RatingBar) findViewById(R.id.ratingBarLevel);
		mTxtNo = (TextView) findViewById(R.id.textViewID);
		mTxtQ = (TextView) findViewById(R.id.textViewQusetion);
		mTxtA = (TextView) findViewById(R.id.textViewAnswer);
		mTxtD = (TextView) findViewById(R.id.textViewData);
		mViewBefore = findViewById(R.id.layoutBefore);
		mViewAfter = findViewById(R.id.layoutAfter);

		// アイコン位置設定
		if (mIcon == 1) {
			// 右側に再設定
			int chk = R.drawable.btn_check;
			int ng = R.drawable.btn_ng;
			int ok = R.drawable.btn_ok;
			btnChk.setCompoundDrawablesWithIntrinsicBounds(0, 0, chk, 0);
			btnNG.setCompoundDrawablesWithIntrinsicBounds(0, 0, ng, 0);
			btnOK.setCompoundDrawablesWithIntrinsicBounds(0, 0, ok, 0);
		}

		// 結果選択欄表示設定
		switch (mMode) {
		case Data.STAT_QUESTION:
			// break;
		case Data.STAT_ANSWER:
			// Check欄表示
			showResultField(false);
			break;
		case Data.STAT_SHOW:
			// OK/NG欄表示
			showResultField(true);
			break;
		default:
			Log.w(TAG, "onCreate() mode=" + mMode);
			break;
		}

		// 初期値データ設定
		if (mDM.getDataList().size() == 0) {
			// UI制御用情報
			List<View> list = new ArrayList<View>();
			list.add(imgFlag);
			list.add(imgEdit);
			list.add(imgSound);
			list.add(imgLink);
			list.add(btnChk);
			list.add(btnNG);
			list.add(btnOK);
			// 試験データ追加タスク呼び出し
			loadData(list, true);
		}
	}

	/*
	 * (非 Javadoc)
	 * 
	 * @see android.app.Activity#onResume()
	 */
	@Override
	protected void onResume() {
		super.onResume();
		Log.d(TAG, "onResume()");

		// 試験データ表示
		showData();

		// ExecutorService開始
		mES = Executors.newSingleThreadExecutor();
	}

	/*
	 * (非 Javadoc)
	 * 
	 * @see android.app.Activity#onPause()
	 */
	@Override
	protected void onPause() {
		super.onPause();
		Log.d(TAG, "onPause()");

		// タスク動作時はキャンセル
		if (mTask != null && mTask.getStatus() == AsyncTask.Status.RUNNING) {
			Log.w(TAG, "onPause()=RUNNING");
			// キャンセル
			mTask.cancel(true);
		}

		// ExecutorService終了
		final long TIMEOUT = 100;
		mES.shutdown();
		try {
			// タスク終了待ち
			if (!mES.awaitTermination(TIMEOUT, TimeUnit.MILLISECONDS)) {
				mES.shutdownNow();
				Log.w(TAG, "onPause()=TIMEOUT");
			}
		} catch (InterruptedException e) {
			mES.shutdownNow();
			Thread.currentThread().interrupt();
			Log.e(TAG, "onPause()=InterruptedException");
			e.printStackTrace();
		}
	}

	/*
	 * (非 Javadoc)
	 * 
	 * @see android.app.Activity#onSaveInstanceState(android.os.Bundle)
	 */
	@Override
	protected void onSaveInstanceState(Bundle outState) {
		super.onSaveInstanceState(outState);
		Log.d(TAG, "onSaveInstanceState()");

		// 状態保存
		outState.putSerializable(IS_DATA, mDM);
	}

	/*
	 * (非 Javadoc)
	 * 
	 * @see android.app.Activity#onCreateDialog(int)
	 */
	@Override
	protected Dialog onCreateDialog(int id) {

		switch (id) {
		case DIALOG_FLAG:
			// フラグ選択ダイアログ生成
			return getDialogFlag();
		case DIALOG_EDIT:
			// メモ編集ダイアログ生成
			return getDialogEdit();
		case DIALOG_RESULT:
			// 試験結果ダイアログ生成
			return getDialogResult();
		case DIALOG_SEEK:
			// 位置指定ダイアログ生成
			return getDialogSeek();
		default:
			Log.w(TAG, "onCreateDialog() id=" + id);
			return null;
		}
	}

	/*
	 * (非 Javadoc)
	 * 
	 * @see android.app.Activity#onPrepareDialog(int, android.app.Dialog)
	 */
	@Override
	protected void onPrepareDialog(int id, Dialog dialog) {

		switch (id) {
		case DIALOG_FLAG:
			// フラグ選択ダイアログ準備
			// 処理無し
			break;
		case DIALOG_EDIT:
			// メモ編集ダイアログ準備
			setDialogEdit(dialog);
			break;
		case DIALOG_RESULT:
			// 試験結果ダイアログ準備
			setDialogResult(dialog);
			break;
		case DIALOG_SEEK:
			// 位置指定ダイアログ準備
			setDialogSeek(dialog);
			break;
		default:
			Log.w(TAG, "onPrepareDialog() id=" + id);
			break;
		}
	}

	/*
	 * (非 Javadoc)
	 * 
	 * @see android.app.Activity#onCreateOptionsMenu(android.view.Menu)
	 */
	@Override
	public boolean onCreateOptionsMenu(Menu menu) {

		getMenuInflater().inflate(R.menu.sub, menu);

		return true;
	}

	/*
	 * (非 Javadoc)
	 * 
	 * @see android.app.Activity#onMenuItemSelected(int, android.view.MenuItem)
	 */
	@SuppressWarnings("deprecation")
	@Override
	public boolean onMenuItemSelected(int featureId, MenuItem item) {

		int id = item.getItemId();
		switch (id) {
		case R.id.menu_seek:
			// 位置指定ダイアログ表示
			showDialog(DIALOG_SEEK);
			break;
		default:
			Log.w(TAG, "onMenuItemSelected() id=" + id);
			break;
		}

		return true;
	}

	/*
	 * (非 Javadoc)
	 * 
	 * @see android.app.Activity#finish()
	 */
	@Override
	public void finish() {

		// 応答設定
		Intent intent = new Intent();
		Bundle ext = new Bundle();
		ext.putInt(Common.INTENT_INDEX, mIndex);
		ext.putInt(Common.INTENT_BASE, mDM.getBasePos());
		intent.putExtras(ext);
		setResult(RESULT_OK, intent);

		super.finish();
		// overridePendingTransition(0, 0);
	}

	/**
	 * フラグ選択ダイアログ生成
	 * 
	 * @return フラグ選択ダイアログ
	 */
	private AlertDialog getDialogFlag() {

		// ダイアログ生成
		AlertDialog.Builder builder = new AlertDialog.Builder(this);
		builder.setCancelable(false);
		builder.setTitle(getString(R.string.item_flag));
		// イベントリスナ設定
		builder.setNegativeButton(android.R.string.cancel, null);
		// アダプタ設定
		FlagAdapter adapter = new FlagAdapter(this,
				Common.getFlagItemList(getApplicationContext()),
				R.layout.dlg_flag, new String[] { Common.FLAG_TEXT },
				new int[] { R.id.textView });
		builder.setAdapter(adapter, new DialogInterface.OnClickListener() {
			@Override
			public void onClick(DialogInterface dialog, int which) {
				// 選択フラグ更新
				mDM.setFlag(which);
				// 試験データ表示
				// showData();ではなく直接変更
				Common.setBackgroundBorder(mTxtQ, which);
				// 試験データ更新タスク呼び出し
				saveData();
			}
		});

		return builder.create();
	}

	/**
	 * メモ編集ダイアログ生成
	 * 
	 * @return メモ編集ダイアログ
	 */
	private AlertDialog getDialogEdit() {

		// ダイアログ生成
		AlertDialog.Builder builder = new AlertDialog.Builder(this);
		builder.setCancelable(false);
		builder.setTitle(getString(R.string.item_edit));
		// インフレート対象にダイアログ用テーマを反映
		LayoutInflater inflater = builder.create().getLayoutInflater();
		View view = inflater.inflate(R.layout.dlg_edit, null);
		// ビュー取得
		final EditText edit = (EditText) view.findViewById(R.id.editText);
		// イベントリスナ設定
		builder.setPositiveButton(android.R.string.ok,
				new DialogInterface.OnClickListener() {
					@Override
					public void onClick(DialogInterface dialog, int which) {
						// 選択メモ更新
						mDM.setData2(edit.getText().toString());
						// 試験データ表示
						showData();
						// 試験データ更新タスク呼び出し
						saveData();
					}
				});
		builder.setNegativeButton(android.R.string.cancel, null);

		builder.setView(view);
		return builder.create();
	}

	/**
	 * 試験結果ダイアログ生成
	 * 
	 * @return 試験結果ダイアログ
	 */
	private AlertDialog getDialogResult() {

		// ダイアログ生成
		AlertDialog.Builder builder = new AlertDialog.Builder(this);
		builder.setCancelable(false);
		builder.setTitle(getString(R.string.title_resultdialog));
		// インフレート対象にダイアログ用テーマを反映
		LayoutInflater inflater = builder.create().getLayoutInflater();
		View view = inflater.inflate(R.layout.dlg_result, null);
		// イベントリスナ設定
		builder.setPositiveButton(R.string.label_next,
				new DialogInterface.OnClickListener() {
					@Override
					public void onClick(DialogInterface dialog, int which) {
						doClickResultSelect(which);
					}
				});
		builder.setNegativeButton(R.string.label_retry,
				new DialogInterface.OnClickListener() {
					@Override
					public void onClick(DialogInterface dialog, int which) {
						doClickResultSelect(which);
					}
				});

		builder.setView(view);
		return builder.create();
	}

	/**
	 * 位置指定ダイアログ生成
	 * 
	 * @return 位置指定ダイアログ
	 */
	private AlertDialog getDialogSeek() {

		// ダイアログ生成
		AlertDialog.Builder builder = new AlertDialog.Builder(this);
		builder.setCancelable(false);
		builder.setTitle(getString(R.string.menu_seek));
		// インフレート対象にダイアログ用テーマを反映
		LayoutInflater inflater = builder.create().getLayoutInflater();
		View view = inflater.inflate(R.layout.dlg_seek, null);
		// ビュー取得
		final TextView text = (TextView) view.findViewById(R.id.textView);
		final SeekBar seek = (SeekBar) view.findViewById(R.id.seekBar);
		// 最大値＆移動単位設定
		seek.setMax((mCount - 1) / mSuite);
		seek.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {
			@Override
			public void onProgressChanged(SeekBar seekBar, int progress,
					boolean fromUser) {
				// 表示は1から
				text.setText(progress * mSuite + 1 + " / " + mCount);
			}

			@Override
			public void onStartTrackingTouch(SeekBar seekBar) {
			}

			@Override
			public void onStopTrackingTouch(SeekBar seekBar) {
			}
		});
		// イベントリスナ設定
		builder.setPositiveButton(android.R.string.ok,
				new DialogInterface.OnClickListener() {
					@Override
					public void onClick(DialogInterface dialog, int which) {
						// データ先頭更新
						mDM.setBasePos(seek.getProgress() * mSuite);
					}
				});
		builder.setNegativeButton(android.R.string.cancel, null);

		builder.setView(view);
		return builder.create();
	}

	/**
	 * メモ編集ダイアログ準備
	 * 
	 * @param dialog
	 *            ダイアログ
	 */
	private void setDialogEdit(Dialog dialog) {

		// 現状メモ設定
		EditText edit = (EditText) dialog.findViewById(R.id.editText);
		edit.setText(mDM.getData().data2);
	}

	/**
	 * 試験結果ダイアログ準備
	 * 
	 * @param dialog
	 *            ダイアログ
	 */
	private void setDialogResult(Dialog dialog) {

		// 試験データ準備状態確認
		if (mDM.getTempList().size() == 0) {
			// 試験データ準備完了まで次へボタン無効化
			if (dialog instanceof AlertDialog) {
				// UI制御用情報
				List<View> list = new ArrayList<View>();
				list.add(((AlertDialog) dialog)
						.getButton(DialogInterface.BUTTON_POSITIVE));
				// 試験データ追加タスク呼び出し
				loadData(list, false);
			}
		}

		// OK結果設定
		TextView ok = (TextView) dialog.findViewById(R.id.textViewOK);
		ok.setText(Integer.toString(mDM.getOKCount()));
		// NG結果設定
		TextView ng = (TextView) dialog.findViewById(R.id.textViewNG);
		ng.setText(Integer.toString(mDM.getNGCount()));
	}

	/**
	 * 位置指定ダイアログ準備
	 * 
	 * @param dialog
	 *            ダイアログ
	 */
	private void setDialogSeek(Dialog dialog) {

		// 現状データ先頭設定
		TextView text = (TextView) dialog.findViewById(R.id.textView);
		SeekBar seek = (SeekBar) dialog.findViewById(R.id.seekBar);
		int pos = mDM.getBasePos();
		// 表示は1から
		text.setText(pos + 1 + " / " + mCount);
		// 一旦クリアしないとバーの色が更新されない
		seek.setProgress(0);
		seek.setProgress(pos / mSuite);
	}

	/**
	 * Flagアイコン処理
	 * 
	 * @param view
	 *            View
	 */
	@SuppressWarnings("deprecation")
	private void doClickFlag(View view) {

		// フラグ選択ダイアログ表示
		showDialog(DIALOG_FLAG);
	}

	/**
	 * Editアイコン処理
	 * 
	 * @param view
	 *            View
	 */
	@SuppressWarnings("deprecation")
	private void doClickEdit(View view) {

		// メモ編集ダイアログ表示
		showDialog(DIALOG_EDIT);
	}

	/**
	 * Soundアイコン処理
	 * 
	 * @param view
	 *            View
	 */
	private void doClickSound(View view) {

		// TODO
		Log.d(TAG, "SOUND");
	}

	/**
	 * Linkアイコン処理
	 * 
	 * @param view
	 *            View
	 */
	private void doClickLink(View view) {

		// TODO
		Log.d(TAG, "LINK");
	}

	/**
	 * Checkボタン処理
	 */
	private void doClickCheck() {

		switch (mMode) {
		case Data.STAT_QUESTION:
			// break;
		case Data.STAT_ANSWER:
			// 表示状態更新
			mDM.setStat(Data.STAT_SHOW);
			// 試験データ表示
			showData();
			// OK/NG欄表示
			showResultField(true);
			break;
		default:
			Log.w(TAG, "doClickCheck() mode=" + mMode);
			break;
		}
	}

	/**
	 * NGボタン選択処理
	 */
	@SuppressWarnings("deprecation")
	private void doClickNG() {

		switch (mMode) {
		case Data.STAT_QUESTION:
			// break;
		case Data.STAT_ANSWER:
			// Check欄表示
			showResultField(false);
			// 表示状態更新
			mDM.setStat(mMode);
			// break;
			//$FALL-THROUGH$
		case Data.STAT_SHOW:
			// NG結果更新
			mDM.addNG();
			// 試験データ位置更新
			if (mDM.setNextPos()) {
				// 試験データ表示
				showData();
			} else {
				// 試験データリスト更新タスク呼び出し
				saveDataList();
				// 試験結果ダイアログ表示
				showDialog(DIALOG_RESULT);
			}
			break;
		default:
			Log.w(TAG, "doClickNG() mode=" + mMode);
			break;
		}
	}

	/**
	 * OKボタン選択処理
	 */
	@SuppressWarnings("deprecation")
	private void doClickOK() {

		switch (mMode) {
		case Data.STAT_QUESTION:
			// break;
		case Data.STAT_ANSWER:
			// Check欄表示
			showResultField(false);
			// 表示状態更新
			mDM.setStat(mMode);
			// break;
			//$FALL-THROUGH$
		case Data.STAT_SHOW:
			// OK結果更新
			mDM.addOK();
			// 試験データ位置更新
			if (mDM.setNextPos()) {
				// 試験データ表示
				showData();
			} else {
				// 試験データリスト更新タスク呼び出し
				saveDataList();
				// 試験結果ダイアログ表示
				showDialog(DIALOG_RESULT);
			}
			break;
		default:
			Log.w(TAG, "doClickOK() mode=" + mMode);
			break;
		}
	}

	/**
	 * Result選択処理
	 * 
	 * @param which
	 *            選択結果
	 */
	private void doClickResultSelect(int which) {

		// この時点では試験データ準備完了
		switch (which) {
		case DialogInterface.BUTTON_POSITIVE:
			// 次回試験データ先頭＝試験データ先頭＋試験単位
			int base = mDM.getBasePos() + mSuite;
			// 項目数超過時は初期化
			if (base >= mCount) {
				base = 0;
			}
			// データ先頭更新
			mDM.setBasePos(base);

			// 次へ
			mDM.setNextPage();
			// 試験データ表示
			showData();
			break;
		case DialogInterface.BUTTON_NEGATIVE:
			// 再試験
			mDM.setZeroPos();
			// 試験データ表示
			showData();
			break;
		default:
			Log.w(TAG, "doClickResultSelect() which=" + which);
			break;
		}
	}

	/**
	 * 結果選択欄表示
	 * 
	 * @param flag
	 *            表示状態
	 */
	private void showResultField(boolean flag) {

		if (flag) {
			// OK/NG欄表示
			mViewBefore.setVisibility(View.GONE);
			mViewAfter.setVisibility(View.VISIBLE);
		} else {
			// Check欄表示
			mViewBefore.setVisibility(View.VISIBLE);
			mViewAfter.setVisibility(View.GONE);
		}
	}

	/**
	 * 試験データ表示
	 */
	private void showData() {

		// 表示データ取得
		Data data = mDM.getData();
		// 取得失敗
		if (data.num == 0) {
			return;
		}

		// レーティング
		mRateLv.setRating(data.level);
		// 試験中データ位置
		mTxtNo.setText(mDM.getDataPos() + 1 + " / " + mDM.getDataList().size());
		// 質問欄背景色
		Common.setBackgroundBorder(mTxtQ, data.flag);

		// 質問欄設定
		String q = data.question;
		if (data.data1.length() > 0) {
			/* TODO 発音記号追加 */
			q += " / <small>" + data.data1 + "</small>";
		}
		CharSequence cs = Html.fromHtml(q);

		// 文字列設定
		switch (data.stat & Data.STAT_SHOW) {
		case Data.STAT_QUESTION:
			mTxtQ.setText(cs);
			mTxtA.setText("");
			mTxtD.setText(data.data2);
			break;
		case Data.STAT_ANSWER:
			mTxtQ.setText("");
			mTxtA.setText(data.answer);
			mTxtD.setText(data.data2);
			break;
		case Data.STAT_SHOW:
			mTxtQ.setText(cs);
			mTxtA.setText(data.answer);
			mTxtD.setText(data.data2);
			break;
		default:
			Log.w(TAG, "showData() stat=" + data.stat);
			break;
		}
	}

	/**
	 * 試験データ更新タスク呼び出し
	 */
	private void saveData() {

		Data data = mDM.getData();

		// 試験データ更新タスク依頼
		try {
			if (mES.submit(new DBAccess.SaveDataTask(getApplicationContext(),
					mIndex, data)) == null) {
				Log.w(TAG, "saveData() Future==null");
			}
		} catch (RejectedExecutionException e) {
			Log.e(TAG, "saveData()=RejectedExecutionException");
			e.printStackTrace();
		}
	}

	/**
	 * 試験データリスト更新タスク呼び出し
	 */
	private void saveDataList() {

		List<Data> list = mDM.getDataList();

		// 試験データリスト更新タスク依頼
		try {
			if (mES.submit(new DBAccess.SaveDataListTask(
					getApplicationContext(), mIndex, list)) == null) {
				Log.w(TAG, "saveDataList() Future==null");
			}
		} catch (RejectedExecutionException e) {
			Log.e(TAG, "saveDataList()=RejectedExecutionException");
			e.printStackTrace();
		}
	}

	/** 試験データ追加タスク */
	private AsyncTask<Void, Void, Integer> mTask = null;

	/**
	 * 試験データ追加タスク呼び出し
	 * 
	 * @param list
	 *            無効化ビューリスト
	 * @param init
	 *            true:初期値データ追加/false:その他データ追加
	 */
	private void loadData(final List<View> list, final boolean init) {

		// 試験データ追加タスク動作時は処理無し
		if (mTask != null && mTask.getStatus() == AsyncTask.Status.RUNNING) {
			Log.w(TAG, "loadData()=RUNNING");
			return;
		}

		// 試験データ追加タスク実行
		mTask = new AsyncTask<Void, Void, Integer>() {

			@Override
			protected void onPreExecute() {
				super.onPreExecute();
				Log.d(TAG, "onPreExecute()");

				// 無効化
				for (View view : list) {
					view.setEnabled(false);
				}
			}

			@Override
			protected void onPostExecute(Integer result) {

				if (result > 0) {
					// 試験データ表示
					showData();
					// 有効化
					for (View view : list) {
						view.setEnabled(true);
					}
				} else {
					// データ無しメッセージ設定
					findViewById(R.id.empty).setVisibility(View.VISIBLE);
					// 消去
					View[] view = { findViewById(R.id.footer),
							findViewById(R.id.v0), findViewById(R.id.v1),
							findViewById(R.id.layoutBefore),
							findViewById(R.id.layoutAfter) };
					for (View v : view) {
						v.setVisibility(View.GONE);
					}
				}

				Log.d(TAG, "onPostExecute()=" + result);
				super.onPostExecute(result);
			}

			@Override
			protected Integer doInBackground(Void... params) {
				Log.d(TAG, "doInBackground()");

				// 次回試験データ先頭＝試験データ先頭＋試験単位
				int base = mDM.getBasePos();
				// 初期値データ以外の場合のみ試験単位を加算
				if (!init) {
					base += mSuite;
				}
				// 項目数超過時は初期化
				if (base >= mCount) {
					base = 0;
				}

				// 単語帳DBデータリスト取得
				List<Data> temp = DBAccess.getDBDataList(
						getApplicationContext(), mIndex, base, mSuite, mSort,
						null);
				// 表示状態設定
				for (int i = 0; i < temp.size(); i++) {
					temp.get(i).stat = mMode;
				}
				// 一時保存データリスト追加
				mDM.addTempList(temp);

				// 初期値データの場合は初期設定が必要
				if (init) {
					mDM.setNextPage();
				}

				return temp.size();
			};
		}.execute();

	}

}
