package eu.tpmusielak.securephoto.camera;
import android.app.Activity;
import android.app.Dialog;
import android.content.*;
import android.content.pm.ActivityInfo;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.IBinder;
import android.preference.PreferenceManager;
import android.util.Pair;
import android.view.*;
import android.widget.*;
import eu.tpmusielak.securephoto.R;
import eu.tpmusielak.securephoto.communication.CommunicationService;
import eu.tpmusielak.securephoto.container.SPFileHandler;
import eu.tpmusielak.securephoto.container.SPImageHandler;
import eu.tpmusielak.securephoto.container.SPImageRollHandler;
import eu.tpmusielak.securephoto.container.VerifierProvider;
import eu.tpmusielak.securephoto.container.wrapper.SPFileWrapper;
import eu.tpmusielak.securephoto.verification.SCVerifierManager;
import eu.tpmusielak.securephoto.verification.Verifier;
import eu.tpmusielak.securephoto.verification.VerifierGUIReceiver;
import eu.tpmusielak.securephoto.viewer.OpenImage;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Timer;
import java.util.concurrent.atomic.AtomicInteger;
/**
* Created by IntelliJ IDEA.
* User: enx
* Date: 27.11.11
* Time: 14:01
*/
public class TakeImage extends Activity implements VerifierGUIReceiver, CameraReceiver, VerifierProvider {
private CameraHandler cameraHandler;
private Button shutterButton;
private Button saveModeButton;
private Button cameraSettingsButton;
private Button verifierSettingsButton;
private Button reviewImageButton;
private ProgressBar backgroundOperationBar;
private AtomicInteger backgroundOpsCounter;
private TextView baseStationDisplay;
private CommunicationService communicationService;
private SCVerifierManager verifierManager;
private List<Verifier> verifiers;
private Map<SaveMode, SPFileHandler> fileHandlers;
private SPFileHandler fileHandler;
private SaveMode saveMode;
private Timer timeUpdateTimer;
private SharedPreferences preferences;
private ViewGroup optionsPane;
private ViewGroup pluginsPane;
private SPFileWrapper lastImageWrapper;
private ServiceConnection communicationServiceConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
communicationService = ((CommunicationService.CommuncationServiceBinder) iBinder).getService();
}
public void onServiceDisconnected(ComponentName componentName) {
}
};
private ServiceConnection verifierServiceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
verifierManager = ((SCVerifierManager.VerifierServiceBinder) iBinder).getService();
verifierManager.bindToGUI(TakeImage.this);
verifiers = verifierManager.getVerifiers();
}
@Override
public void onServiceDisconnected(ComponentName componentName) {
}
};
@SuppressWarnings("unchecked")
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
cameraHandler = new CameraHandler(this);
preferences = PreferenceManager.getDefaultSharedPreferences(this);
backgroundOpsCounter = new AtomicInteger(0);
//TODO: replace with user-definable default mode
saveMode = SaveMode.IMAGE_ROLL;
setupScreen();
cameraHandler.setupCamera();
Intent intent = new Intent(this, CommunicationService.class);
bindService(intent, communicationServiceConnection, Context.BIND_AUTO_CREATE);
Intent verifierServiceIntent = new Intent(this, SCVerifierManager.class);
bindService(verifierServiceIntent, verifierServiceConnection, Context.BIND_AUTO_CREATE);
fileHandlers = new HashMap<SaveMode, SPFileHandler>();
fileHandlers.put(SaveMode.SINGLE_IMAGE, new SPImageHandler(this));
fileHandlers.put(SaveMode.IMAGE_ROLL, new SPImageRollHandler(this));
fileHandler = fileHandlers.get(saveMode);
}
@SuppressWarnings(value = "unchecked")
private void setupScreen() {
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
setContentView(R.layout.camera_view);
cameraHandler.setCameraPreviewFrame((FrameLayout) findViewById(R.id.preview));
shutterButton = (Button) findViewById(R.id.btn_shutter);
cameraHandler.registerShutterButton(shutterButton);
saveModeButton = (Button) findViewById(R.id.btn_save_mode);
saveModeButton.setOnClickListener(new SaveModeListener(saveModeButton));
verifierSettingsButton = (Button) findViewById(R.id.btn_verifier_settings);
verifierSettingsButton.setOnClickListener(new VerifierSettingsListener());
cameraSettingsButton = (Button) findViewById(R.id.btn_camera_settings);
cameraSettingsButton.setOnClickListener(new CameraSettingsListener());
reviewImageButton = (Button) findViewById(R.id.btn_review_image);
reviewImageButton.setOnClickListener(new ReviewImageListener());
optionsPane = (ViewGroup) findViewById(R.id.options_pane);
pluginsPane = (ViewGroup) findViewById(R.id.plugins_pane);
timeUpdateTimer = new Timer("TimeUpdateTimer");
timeUpdateTimer.scheduleAtFixedRate(new TimeUpdateTask(this), 0, 1000);
String baseStationAddress = preferences.getString("base_station_address", "");
baseStationDisplay = (TextView) findViewById(R.id.camera_base);
baseStationDisplay.setText(baseStationAddress);
backgroundOperationBar = (ProgressBar) findViewById(R.id.camera_save_progress);
backgroundOperationBar.isIndeterminate();
}
private void setFileHandler(SPFileHandler handler) {
handler.onInitialize(TakeImage.this);
fileHandler = handler;
}
private class SaveModeListener implements Button.OnClickListener {
public SaveModeListener(Button saveModeButton) {
saveModeButton.setBackgroundResource(saveMode.getDrawableResID());
}
@Override
public void onClick(View view) {
saveMode = saveMode.switchMode();
setFileHandler(fileHandlers.get(saveMode));
((Button) view).setBackgroundResource(saveMode.getDrawableResID());
}
}
private class VerifierSettingsListener implements Button.OnClickListener {
@Override
public void onClick(View view) {
verifierManager.showVerificationFactors();
}
}
private class CameraSettingsListener implements Button.OnClickListener {
@Override
public void onClick(View view) {
cameraHandler.showCameraSettings();
}
}
private class ReviewImageListener implements View.OnClickListener {
@Override
public void onClick(View view) {
viewImage(lastImageWrapper);
}
}
private void viewImage(SPFileWrapper wrapper) {
if (wrapper == null)
return;
Intent i = new Intent(getContext(), OpenImage.class);
i.putExtra("filename", wrapper.getFile().getAbsolutePath());
i.putExtra("filewrapper", wrapper);
getContext().startActivity(i);
}
public Context getContext() {
return this;
}
@Override
public void savePicture(byte[] bytes) {
new SavePictureTask().execute(new byte[][]{bytes});
}
private class SavePictureTask extends AsyncTask<byte[], Void, Pair<SPFileWrapper, String>> {
byte[] pictureData;
@Override
protected void onPreExecute() {
startBackgroundOperation();
}
@Override
protected Pair<SPFileWrapper, String> doInBackground(byte[]... bytes) {
pictureData = bytes[0];
SPFileWrapper fileWrapper = null;
String outcome = null;
try {
fileWrapper = fileHandler.saveFile(pictureData);
} catch (NullPointerException e) {
throw e;
} catch (RuntimeException e) {
outcome = e.toString();
}
return new Pair<SPFileWrapper, String>(fileWrapper, outcome);
}
@Override
protected void onPostExecute(Pair<SPFileWrapper, String> result) {
SPFileWrapper fileWrapper = result.first;
String outcome = result.second;
if (fileWrapper != null) {
Toast.makeText(TakeImage.this, getString(R.string.image_saved_successfully, fileWrapper.getName()), Toast.LENGTH_SHORT).show();
onImageSaved(fileWrapper);
} else
Toast.makeText(TakeImage.this, getString(R.string.error_saving_image, outcome), Toast.LENGTH_SHORT).show();
endBackgroundOperation();
}
}
@Override
protected void onResume() {
super.onResume();
cameraHandler.resumeCamera();
fileHandler.onInitialize(getContext());
}
@Override
protected void onPause() {
cameraHandler.pauseCamera();
super.onPause();
}
@Override
protected void onDestroy() {
verifierManager.unbindFromGUI();
unbindService(verifierServiceConnection);
unbindService(communicationServiceConnection);
super.onDestroy();
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// MenuInflater inflater = getMenuInflater();
// inflater.inflate(R.menu.camera_menu, menu);
return false;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.v_factors:
verifierManager.showVerificationFactors();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
@Override
public ViewGroup getPluginsPane() {
return pluginsPane;
}
public void startBackgroundOperation() {
backgroundOperationBar.setVisibility(View.VISIBLE);
backgroundOpsCounter.incrementAndGet();
}
public void endBackgroundOperation() {
if (backgroundOpsCounter.decrementAndGet() <= 0) {
backgroundOperationBar.setVisibility(View.GONE);
}
}
public void onImageSaved(SPFileWrapper wrapper) {
lastImageWrapper = wrapper;
if (preferences.getBoolean("submit_hash", true)) {
communicationService.notifyPictureTaken(wrapper);
}
if (preferences.getBoolean("review_image", true)) {
viewImage(lastImageWrapper);
}
}
@Override
protected Dialog onCreateDialog(int id) {
return super.onCreateDialog(id);
}
@Override
public List<Verifier> getVerifiers() {
return verifiers;
}
}