package ca.ualberta.cs.cmput301t03app.views;
import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import ca.ualberta.cs.cmput301t03app.R;
import ca.ualberta.cs.cmput301t03app.adapters.AnswerListAdapter;
import ca.ualberta.cs.cmput301t03app.controllers.GeoLocationTracker;
import ca.ualberta.cs.cmput301t03app.controllers.PictureController;
import ca.ualberta.cs.cmput301t03app.controllers.PostController;
import ca.ualberta.cs.cmput301t03app.controllers.PushController;
import ca.ualberta.cs.cmput301t03app.datamanagers.ServerDataManager;
import ca.ualberta.cs.cmput301t03app.models.Answer;
import ca.ualberta.cs.cmput301t03app.models.GeoLocation;
import ca.ualberta.cs.cmput301t03app.models.Question;
import ca.ualberta.cs.cmput301t03app.views.MainActivity.PushThread;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.provider.MediaStore;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.Window;
import android.widget.AdapterView;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.AdapterView.OnItemClickListener;
/**
*
*
*
* This is the Activity responsible for allowing a user to view further details
* about a Question (the Question body text), view answers to a given question,
* as well as add answers, add comments to the question, and add comments to
* answers.
*
*/
public class ViewQuestion extends Activity {
public static final String SET_COMMENT_TYPE = "0";
public static final int COMMENT_ON_QUESTION_KEY = 1;
public static final int COMMENT_ON_ANSWER_KEY = 2;
public static final String QUESTION_ID_KEY = "3";
public static final String ANSWER_ID_KEY = "4";
private final int CAMERA_ACTIVITY_REQUEST_CODE = 12345;
private final int GALLERY_ACTIVITY_REQUEST_CODE = 67890;
protected boolean hasLocation = false;
protected boolean hasPicture = false;
protected GeoLocation location;
protected String cityName;
private PostController pc = new PostController(this);
private PushController pushCtrl = new PushController(this);
private PictureController pictureController = new PictureController(this);
private ArrayList<Answer> answerList = new ArrayList<Answer>();
private static ServerDataManager sdm = new ServerDataManager();
public AlertDialog dialog; // for testing
AnswerListAdapter ala;
Uri imageFileUri;
//UI Objects
private static ImageButton favIcon;
ListView answerListView;
ImageButton upvoteButton;
ImageButton commentButton;
TextView upvote_score;
Button answerButton;
String question_id;
TextView answerCounter;
TextView commentCounter;
ImageView questionPictureButton;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_view_question);
/* Removes the actionbar title text */
getActionBar().setDisplayShowTitleEnabled(false);
// enables the activity icon as a 'home' button. required if
// "android:targetSdkVersion" > 14
getActionBar().setHomeButtonEnabled(true);
Bundle extras = getIntent().getExtras();
question_id = extras.getString("question_id"); // grabbing question to
// be displayed
instantiateViews();
setQuestionText(question_id);
updateAnswerCount();
setListeners();
setFavoriteIcon();
setAnswerAdapter();
updateCommentCount(); // updates comments counter
}
@Override
protected void onResume() {
super.onResume();
updateCommentCount();
ala.updateAdapter(answerList);
setFavoriteIcon();
}
/**
* Creates listeners for the given buttons in the activity
*/
public void setListeners() {
answerButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
answerQuestion();
}
});
// listener to see if click on comment question
commentButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
toCommentActivityQuestion(v);
}
});
// listener to favorite a question
favIcon.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
pc.addFavoriteQuestion(pc.getQuestion(question_id));
favIcon.setImageResource(R.drawable.ic_fav_yes);
setFavoriteIcon();
Toast.makeText(ViewQuestion.this, "Added to Favorites List.",
Toast.LENGTH_SHORT).show();
}
});
// listener to upvote when clicked
upvoteButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
if (pc.checkConnectivity()) {
Integer.toString(pc.getQuestion(question_id).getRating());
increment_upvote();
} else {
pc.cantUpvoteMsg();
}
}
});
questionPictureButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
toPictureActivityQuestion(v);
}
});
}
/**
* Assigns the AnswerListAdapter to the AnswerList and populates it with
* answers to the given Question
*/
public void setAnswerAdapter() {
answerListView = (ListView) findViewById(R.id.answerListView);
populateThisQuestionsAnswers(question_id);
ala = new AnswerListAdapter(this, R.id.answerListView, answerList);
answerListView.setAdapter(ala);
/* Change icon if has Picture for answers */
}
/**
* Gets the list of answers from the question object and
* replaces the answer list displayed.
* @param question_id A string representing a question id
*/
public void populateThisQuestionsAnswers(String question_id) {
answerList.clear();
Log.v("THIS", pc.getQuestion(question_id).getAnswers().toString());
answerList.addAll(pc.getQuestion(question_id).getAnswers());
}
/**
* Returns the view at the specified position.
* @param pos
* @param listView
* @return
*/
public View getViewByPosition(int pos, ListView listView) {
final int firstListItemPosition = listView.getFirstVisiblePosition();
final int lastListItemPosition = firstListItemPosition
+ listView.getChildCount() - 1;
if (pos < firstListItemPosition || pos > lastListItemPosition) {
return listView.getAdapter().getView(pos, null, listView);
} else {
final int childIndex = pos - firstListItemPosition;
return listView.getChildAt(childIndex);
}
}
/**
* Takes a questionId and uses that ID to fill in the various elements of a
* Question in the view.
*
* @param ID
* The id of teh question
*/
public void setQuestionText(String ID) {
Question q;
if (pc.getQuestionsInstance().contains(ID)) {
q = pc.getQuestion(ID);
} else {
q = pc.getQuestionFromLocalSave(ID);
}
TextView q_title = (TextView) findViewById(R.id.question_title);
TextView upvote_score = (TextView) findViewById(R.id.question_upvote_score);
TextView q_body = (TextView) findViewById(R.id.question_text_body);
TextView q_author = (TextView) findViewById(R.id.question_author);
TextView q_date = (TextView) findViewById(R.id.post_timestamp);
TextView q_location = (TextView) findViewById(R.id.question_location1);
upvote_score.setText(Integer.toString(q.getRating()));
q_title.setText(q.getSubject());
q_body.setText(q.getBody());
q_author.setText("By: " + q.getAuthor());
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm");
String date_to_string = sdf.format(q.getDate());
q_date.setText("Posted: " + date_to_string);
if (q.getPicture() != null)
questionPictureButton.setImageResource(R.drawable.ic_picture_yes);
//Sets city name for location
if (q.getGeoLocation()!= null) {
q_location.setText("Location: " + q.getGeoLocation().getCityName());
}
}
/**
* Fills the favorite icon if the question is in the
* user favorite's list
*/
public void setFavoriteIcon() {
if (pc.isQuestionInFavByID(question_id)) {
favIcon.setImageResource(R.drawable.ic_fav_yes);
}
}
/**
* Instantiates the view objects.
*/
public void instantiateViews() {
// thisQuestion = (TextView) findViewById(R.id.question_title);
answerListView = (ListView) findViewById(R.id.answerListView);
favIcon = (ImageButton) findViewById(R.id.question_fav_icon);
upvoteButton = (ImageButton) findViewById(R.id.question_upvote_button);
commentButton = (ImageButton) findViewById(R.id.question_comment_icon);
upvote_score = (TextView) findViewById(R.id.question_upvote_score);
answerButton = (Button) findViewById(R.id.question_answer_button);
answerCounter = (TextView) findViewById(R.id.answer_count);
commentCounter = (TextView) findViewById(R.id.question_comment_count);
answerListView = (ListView) findViewById(R.id.answerListView);
questionPictureButton = (ImageView) findViewById(R.id.question_picture_button);
}
/**
* Starts the ViewComment activity for commenting a question
* @param v View where the click happened
*/
public void toCommentActivityQuestion(View v) {
/* This method takes user to ViewComment activity for questions */
Intent i = new Intent(this, ViewComment.class);
i.putExtra(SET_COMMENT_TYPE, COMMENT_ON_QUESTION_KEY);
i.putExtra(QUESTION_ID_KEY, question_id);
startActivity(i);
}
/**
* Starts the ViewComment activity for commenting an answer
*
* @param v View where the click happened
*/
public void toCommentActivityAnswer(View v) {
/* This method takes user to ViewComment activity for answers */
Answer answer = (Answer) v.getTag();
Intent i = new Intent(this, ViewComment.class);
i.putExtra(SET_COMMENT_TYPE, COMMENT_ON_ANSWER_KEY);
i.putExtra(QUESTION_ID_KEY, question_id);
i.putExtra(ANSWER_ID_KEY, answer.getId());
startActivity(i);
}
/**
* Starts the ViewPicture activity for a question
*
* @param v
* View where the click happened
*/
public void toPictureActivityQuestion(View v) {
/* This method takes user to ViewPicture activity for questions */
if (pc.getQuestion(question_id).getPicture() != null) {
Intent i = new Intent(this, ViewPicture.class);
i.putExtra(SET_COMMENT_TYPE, 1);
i.putExtra(QUESTION_ID_KEY, question_id);
Log.d("click", "Leaving View picture");
startActivity(i);
}
}
/**
* Starts the ViewPicture activity for an answer
*
* @param v
* View where the click happened
*/
public void toPictureActivityAnswer(View v) {
/* This method takes user to ViewPicture activity for answers */
Answer answer = (Answer) v.getTag();
if (pc.getAnswer(answer.getId(), question_id).getPicture() != null) {
Intent i = new Intent(this, ViewPicture.class);
i.putExtra(SET_COMMENT_TYPE, 2);
i.putExtra(QUESTION_ID_KEY, question_id);
i.putExtra(ANSWER_ID_KEY, answer.getId());
startActivity(i);
}
}
/**
* onClick method for adding an answer to the question Prompts the user with
* a dialog box which requests answer body text (answerBodyString) as well
* as a user name (userNameString). When the dialog is complete, the
* adapters update method is called.
*/
public void answerQuestion() {
/* when clicked answer question dialog box pops up here */
LayoutInflater li = LayoutInflater.from(this);
View promptsView = li.inflate(R.layout.activity_post_dialog, null);
final EditText answerBody = (EditText) promptsView
.findViewById(R.id.postBody);
final EditText userName = (EditText) promptsView
.findViewById(R.id.UsernameRespondTextView);
final ImageButton attachImg = (ImageButton) promptsView
.findViewById(R.id.attachImg);
final ProgressBar spinner = (ProgressBar) promptsView
.findViewById(R.id.progressBar1);
spinner.setVisibility(View.GONE);
attachImg.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
pictureChooserDialog();
}
});
final EditText userLocation = (EditText) promptsView
.findViewById(R.id.userLocation2);
CheckBox check = (CheckBox) promptsView
.findViewById(R.id.enableLocation2);
check.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
hasLocation=!hasLocation;
if (hasLocation) {
spinner.setVisibility(View.VISIBLE);
location = new GeoLocation();
GeoLocationTracker locationTracker = new GeoLocationTracker(ViewQuestion.this, location);
locationTracker.getLocation();
// location.setLatitude(53.53333);
// location.setLongitude(-113.5);
//Delay for 7 seconds
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
public void run() {
cityName = pc.getCity(location);
Log.d("Loc","Timer is done");
if (cityName != null) {
userLocation.setText(cityName);
location.setCityName(cityName);
} else {
userLocation.setText("Location not found.");
}
spinner.setVisibility(View.GONE);
}
}, 7000);
}
}
});
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(this); // Create
// a
// new
// AlertDialog
alertDialogBuilder.setView(promptsView);
alertDialogBuilder.setPositiveButton("Answer",
new DialogInterface.OnClickListener() {
@Override
// Building the dialog for adding
public void onClick(DialogInterface dialog, int which) {
String answerBodyString = (String) answerBody.getText()
.toString();
String userNameString = (String) userName.getText()
.toString();
final Answer a = new Answer(answerBodyString, userNameString,
question_id);
if (hasPicture){
Bitmap _bitmapScaled = pictureController.ShrinkBitmap(imageFileUri.getPath(), 200,200);
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
_bitmapScaled.compress(Bitmap.CompressFormat.PNG, 0, bytes);
a.setPicture(bytes.toByteArray());
}
String userLocationString = (String) userLocation.getText()
.toString();
if(hasLocation){
//Set location if location typed by user is same as location found
if (userLocationString.equals(cityName)){
a.setGeoLocation(location);
}
//Find the coordinates of place entered by user and set location
else{
a.setGeoLocation(pc.turnFromCity(userLocationString));
//Testing
GeoLocation testlocation= pc.turnFromCity(userLocationString);
Log.d("Location",Double.toString(testlocation.getLatitude()));
Log.d("Location",Double.toString(testlocation.getLongitude()));
}
}
populateThisQuestionsAnswers(question_id);
pc.getQuestion(question_id).addAnswer(a);
updateAnswerCount();
if(pc.checkConnectivity()) {
Thread thread = new AnswerQuestion(question_id, a);
thread.start();
} else {
pc.addPushAnsAndComm(question_id, a.getId(), null);
}
try {
Thread.currentThread().sleep(250);
} catch (InterruptedException e) {
e.printStackTrace();
}
populateThisQuestionsAnswers(question_id);
ala.updateAdapter(answerList);
hasLocation = false;
}
}).setNegativeButton("Cancel",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
// Do nothing
hasLocation = false;
dialog.cancel();
}
});
final AlertDialog alertDialog = alertDialogBuilder.create();
dialog = alertDialog;
alertDialog.show();
alertDialog.getButton(AlertDialog.BUTTON1).setEnabled(false);
// creating a listener to see if any changes to edit text in dialog
TextWatcher textwatcher = new TextWatcher() {
private void handleText() {
final Button button = alertDialog
.getButton(AlertDialog.BUTTON_POSITIVE);
if (answerBody.getText().length() == 0) { // these checks the
// edittext to make
// sure not empty
// edit text
button.setEnabled(false);
} else if (userName.getText().length() == 0) {
button.setEnabled(false);
} else {
button.setEnabled(true);
}
}
@Override
public void afterTextChanged(Editable s) {
handleText();
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
// do nothing
}
@Override
public void onTextChanged(CharSequence s, int start, int before,
int count) {
// do nothing
}
};
answerBody.addTextChangedListener(textwatcher); // adding listeners to
// the edittexts
userName.addTextChangedListener(textwatcher);
Toast.makeText(this, "Please write your answer", Toast.LENGTH_SHORT)
.show();
}
/**
* onClick method for upvoting the question
* http://stackoverflow.com/questions/2173936/how-to-set-background-color-of-a-view
*/
public void increment_upvote() {
pc.upvoteQuestion(question_id);
upvote_score.setText(Integer.toString(pc.getQuestion(question_id)
.getRating()));
pc.updateQuestionInBank(question_id);
Thread upvoteQuestion = new Upvote(question_id);
upvoteQuestion.start();
}
/**
* Responsible for updating the views answerCounter
*/
public void updateAnswerCount() {
Log.d("click",
"Count"
+ String.valueOf(pc.getQuestion(question_id)
.countAnswers()));
answerCounter.setText("Answers: "
+ String.valueOf(pc.getQuestion(question_id).countAnswers()));
}
/**
* Responsible for updating the views question commentCounter
*/
public void updateCommentCount() {
commentCounter.setText(String.valueOf(pc.getQuestion(question_id)
.countComments()));
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
http://stackoverflow.com/questions/2173936/how-to-set-background-color-of-a-view
getMenuInflater().inflate(R.menu.view_question, menu);
getActionBar().setHomeButtonEnabled(true);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
switch (item.getItemId()) {
case android.R.id.home:
runOnUiThread(doFinish);
break;
}
return (super.onOptionsItemSelected(item));
}
/**
* onClick method for updating answers
*
* @param v
* View where the click happened
*/
public void answerUpvote(View v) {
final Answer answer = (Answer) v.getTag();
pc.upvoteAnswer(answer.getId(), question_id);
ala.notifyChange();
pc.updateQuestionInBank(answer.getParentId());
Thread upvoteAnswer = new Upvote(question_id);
upvoteAnswer.start();
}
private void pictureChooserDialog() {
AlertDialog.Builder myAlertDialog = new AlertDialog.Builder(this);
myAlertDialog.setTitle("Pictures Option");
myAlertDialog.setMessage("Select Picture Mode");
myAlertDialog.setPositiveButton("Gallery",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface arg0, int arg1) {
takeFromGallery();
}
});
myAlertDialog.setNegativeButton("Camera",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface arg0, int arg1) {
takeAPhoto();
}
});
myAlertDialog.show();
}
private void takeAPhoto() {
/*
* Main Activity is getting pretty bloated so I'm trying to move this
* out into the Utils package
*/
String path = Environment.getExternalStorageDirectory()
.getAbsolutePath() + "/MyCameraTest";
File folder = new File(path);
if (!folder.exists()) {
folder.mkdir();
}
String imagePathAndFileName = path + File.separator
+ String.valueOf(System.currentTimeMillis()) + ".jpg";
// timestamp as part of the filename
File imageFile = new File(imagePathAndFileName);
imageFileUri = Uri.fromFile(imageFile);
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, imageFileUri);
startActivityForResult(intent, CAMERA_ACTIVITY_REQUEST_CODE);
// matches the ID to the request code in onActivityResult
}
private void takeFromGallery() {
Intent intent = new Intent(Intent.ACTION_PICK,
android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
intent.setType("image/*");
intent.setAction(Intent.ACTION_GET_CONTENT);
startActivityForResult(Intent.createChooser(intent,
"Select Picture"), GALLERY_ACTIVITY_REQUEST_CODE);
}
/**
* This method is run after returning back from camera activity:
*/
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) {
case CAMERA_ACTIVITY_REQUEST_CODE:
if (resultCode == RESULT_OK) {
hasPicture = true;
} else if (resultCode == RESULT_CANCELED) {
}
break;
case GALLERY_ACTIVITY_REQUEST_CODE:
if (resultCode == RESULT_OK) {
hasPicture = true;
Uri galleryImageUri = data.getData();
File imageFile = new File(pictureController.getRealPathFromURI(galleryImageUri));
imageFileUri = Uri.fromFile(imageFile);
}
break;
}
}
/**
* Thread that is used to push an Answer to the server.
*
*/
class AnswerQuestion extends Thread {
private String qID;
private Answer answer;
public AnswerQuestion(String qID, Answer answer) {
this.qID = qID;
this.answer = answer;
}
@Override
public void run() {
pushCtrl.answerAQuestionToServer(this.answer, this.qID);
}
}
/**
* Thread is used to push upvotes to questions
*
*/
class Upvote extends Thread {
private String qID;
public Upvote(String qID) {
this.qID = qID;
}
public void run() {
sdm.updateQuestion(pc.getQuestion(this.qID));
try {
Thread.sleep(250);
} catch(InterruptedException e) {
e.printStackTrace();
}
}
}
/**
* Instructs the Thread to terminate
*/
private Runnable doFinish = new Runnable() {
public void run() {
finish();
}
};
// Used for testing
public AlertDialog getDialog() {
return this.dialog;
}
}