/*
DroidFish - An Android chess program.
Copyright (C) 2013 Peter Ă–sterlund, peterosterlund2@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.petero.droidfish.activities;
import java.io.File;
import java.util.ArrayList;
import java.util.concurrent.CountDownLatch;
import org.petero.droidfish.ChessBoardPlay;
import org.petero.droidfish.ColorTheme;
import org.petero.droidfish.R;
import org.petero.droidfish.Util;
import org.petero.droidfish.activities.FENFile.FenInfo;
import org.petero.droidfish.activities.FENFile.FenInfoResult;
import org.petero.droidfish.gamelogic.ChessParseError;
import org.petero.droidfish.gamelogic.Pair;
import org.petero.droidfish.gamelogic.Position;
import org.petero.droidfish.gamelogic.TextIO;
import android.app.Activity;
import android.app.Dialog;
import android.app.DialogFragment;
import android.app.Fragment;
import android.app.ListActivity;
import android.app.ProgressDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.content.res.Configuration;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.AdapterView.OnItemLongClickListener;
public class LoadFEN extends ListActivity {
private static ArrayList<FenInfo> fensInFile = new ArrayList<FenInfo>();
private static boolean cacheValid = false;
private FENFile fenFile;
private ProgressDialog progress;
private FenInfo selectedFi = null;
private ArrayAdapter<FenInfo> aa = null;
private SharedPreferences settings;
private int defaultItem = 0;
private String lastFileName = "";
private long lastModTime = -1;
private Thread workThread = null;
private CountDownLatch progressLatch = null;
private ChessBoardPlay cb;
private Button okButton;
private Button cancelButton;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
settings = PreferenceManager.getDefaultSharedPreferences(this);
Util.setFullScreenMode(this, settings);
if (savedInstanceState != null) {
defaultItem = savedInstanceState.getInt("defaultItem");
lastFileName = savedInstanceState.getString("lastFenFileName");
if (lastFileName == null) lastFileName = "";
lastModTime = savedInstanceState.getLong("lastFenModTime");
} else {
defaultItem = settings.getInt("defaultItem", 0);
lastFileName = settings.getString("lastFenFileName", "");
lastModTime = settings.getLong("lastFenModTime", 0);
}
Intent i = getIntent();
String action = i.getAction();
String fileName = i.getStringExtra("org.petero.droidfish.pathname");
if (action.equals("org.petero.droidfish.loadFen")) {
fenFile = new FENFile(fileName);
progressLatch = new CountDownLatch(1);
showProgressDialog();
final LoadFEN lfen = this;
workThread = new Thread(new Runnable() {
public void run() {
try {
progressLatch.await();
} catch (InterruptedException e) {
setResult(RESULT_CANCELED);
finish();
return;
}
if (!readFile())
return;
runOnUiThread(new Runnable() {
public void run() {
lfen.showList();
}
});
}
});
workThread.start();
} else if (action.equals("org.petero.droidfish.loadNextFen") ||
action.equals("org.petero.droidfish.loadPrevFen")) {
fenFile = new FENFile(fileName);
boolean next = action.equals("org.petero.droidfish.loadNextFen");
final int loadItem = defaultItem + (next ? 1 : -1);
if (loadItem < 0) {
Toast.makeText(getApplicationContext(), R.string.no_prev_fen,
Toast.LENGTH_SHORT).show();
setResult(RESULT_CANCELED);
finish();
} else {
workThread = new Thread(new Runnable() {
public void run() {
if (!readFile())
return;
runOnUiThread(new Runnable() {
public void run() {
if (loadItem >= fensInFile.size()) {
Toast.makeText(getApplicationContext(), R.string.no_next_fen,
Toast.LENGTH_SHORT).show();
setResult(RESULT_CANCELED);
finish();
} else {
defaultItem = loadItem;
sendBackResult(fensInFile.get(loadItem));
}
}
});
}
});
workThread.start();
}
} else { // Unsupported action
setResult(RESULT_CANCELED);
finish();
}
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putInt("defaultItem", defaultItem);
outState.putString("lastFenFileName", lastFileName);
outState.putLong("lastFenModTime", lastModTime);
}
@Override
protected void onPause() {
Editor editor = settings.edit();
editor.putInt("defaultItem", defaultItem);
editor.putString("lastFenFileName", lastFileName);
editor.putLong("lastFenModTime", lastModTime);
editor.commit();
super.onPause();
}
@Override
protected void onDestroy() {
if (workThread != null) {
workThread.interrupt();
try {
workThread.join();
} catch (InterruptedException e) {
}
workThread = null;
}
super.onDestroy();
}
private final void showList() {
progress = null;
removeProgressDialog();
setContentView(R.layout.load_fen);
cb = (ChessBoardPlay)findViewById(R.id.loadfen_chessboard);
okButton = (Button)findViewById(R.id.loadfen_ok);
cancelButton = (Button)findViewById(R.id.loadfen_cancel);
okButton.setEnabled(false);
okButton.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
if (selectedFi != null)
sendBackResult(selectedFi);
}
});
cancelButton.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
setResult(RESULT_CANCELED);
finish();
}
});
Util.overrideViewAttribs(findViewById(android.R.id.content));
aa = new ArrayAdapter<FenInfo>(this, R.layout.select_game_list_item, fensInFile) {
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View view = super.getView(position, convertView, parent);
if (view instanceof TextView) {
int fg = ColorTheme.instance().getColor(ColorTheme.FONT_FOREGROUND);
((TextView) view).setTextColor(fg);
}
return view;
}
};
setListAdapter(aa);
final ListView lv = getListView();
lv.setSelectionFromTop(defaultItem, 0);
lv.setFastScrollEnabled(true);
lv.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int pos, long id) {
selectedFi = aa.getItem(pos);
if (selectedFi == null)
return;
defaultItem = pos;
Position chessPos;
try {
chessPos = TextIO.readFEN(selectedFi.fen);
} catch (ChessParseError e2) {
chessPos = e2.pos;
}
if (chessPos != null) {
cb.setPosition(chessPos);
okButton.setEnabled(true);
}
}
});
lv.setOnItemLongClickListener(new OnItemLongClickListener() {
@Override
public boolean onItemLongClick(AdapterView<?> parent, View view, int pos, long id) {
selectedFi = aa.getItem(pos);
if (selectedFi == null)
return false;
defaultItem = pos;
Position chessPos;
try {
chessPos = TextIO.readFEN(selectedFi.fen);
} catch (ChessParseError e2) {
chessPos = e2.pos;
}
if (chessPos != null)
sendBackResult(selectedFi);
return true;
}
});
lv.requestFocus();
}
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
if (cb != null) {
Position pos = cb.pos;
showList();
cb.setPosition(pos);
okButton.setEnabled(selectedFi != null);
}
}
public static class ProgressFragment extends DialogFragment {
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
LoadFEN a = (LoadFEN)getActivity();
ProgressDialog progress = new ProgressDialog(a);
progress.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
progress.setTitle(R.string.reading_fen_file);
a.progress = progress;
a.progressLatch.countDown();
return progress;
}
@Override
public void onCancel(DialogInterface dialog) {
super.onCancel(dialog);
Activity a = getActivity();
if (a instanceof LoadFEN) {
Thread thr = ((LoadFEN)a).workThread;
if (thr != null)
thr.interrupt();
}
}
}
private void showProgressDialog() {
ProgressFragment f = new ProgressFragment();
f.show(getFragmentManager(), "progress");
}
private void removeProgressDialog() {
Fragment f = getFragmentManager().findFragmentByTag("progress");
if (f instanceof DialogFragment)
((DialogFragment)f).dismiss();
}
private final boolean readFile() {
String fileName = fenFile.getName();
if (!fileName.equals(lastFileName))
defaultItem = 0;
long modTime = new File(fileName).lastModified();
if (cacheValid && (modTime == lastModTime) && fileName.equals(lastFileName))
return true;
fenFile = new FENFile(fileName);
Pair<FenInfoResult, ArrayList<FenInfo>> p = fenFile.getFenInfo(this, progress);
if (p.first != FenInfoResult.OK) {
fensInFile = new ArrayList<FenInfo>();
if (p.first == FenInfoResult.OUT_OF_MEMORY) {
runOnUiThread(new Runnable() {
public void run() {
Toast.makeText(getApplicationContext(), R.string.file_too_large,
Toast.LENGTH_SHORT).show();
}
});
}
setResult(RESULT_CANCELED);
finish();
return false;
}
fensInFile = p.second;
cacheValid = true;
lastModTime = modTime;
lastFileName = fileName;
return true;
}
private final void sendBackResult(FenInfo fi) {
String fen = fi.fen;
if (fen != null) {
setResult(RESULT_OK, (new Intent()).setAction(fen));
finish();
} else {
setResult(RESULT_CANCELED);
finish();
}
}
}